Designing Modern Web Forms with HTML 5 and CSS3

Recently I noticed that many web developers are still using HTML tables to layout their forms. Mainly it is because people stick with what they know, and have never taken the time to learn a better way. Once you learn to layout forms with standards compliant CSS it is actually quite easy!

View Demo Download Code

We will be using HTML5 and CSS3 to achieve great style and functionality without causing problems in less capable browsers. To be clear, this code will not look exactly the same in every browser. We are designing for the most advanced browsers, then making sure it still degrades gracefully.

Starting with the right markup.

Here we are using HTML 5 to code the form. Take a look:

<div id="registration">
<h2>Create an Account</h2>

<form id="RegisterUserForm" action="" method="post">
<label for="name">Name</label>
<input id="name" name="name" type="text" class="text" value="" />

<label for="tel">Phone Number</label>
<input id="tel" name="tel" type="tel" class="text" value="" />

<label for="email">Email</label>
<input id="email" name="email" type="email" class="text" value="" />

<label for="password">Password</label>
<input id="password" name="password" class="text" type="password" />

<p><input id="acceptTerms" name="acceptTerms" type="checkbox" />
<label for="acceptTerms">
I agree to the <a href="">Terms and Conditions</a> and <a href="">Privacy Policy</a>

<button id="registerNew" type="submit">Register</button>



Note the input types. Instead of only using the usual “name” and “password” I also added “tel” and “email”. Most browsers don’t render anything different here, but it makes a big difference for the user experience on Safari mobile (iPhone and iPad). The key difference is a rearranged keyboard to focus on the type of input. Email adds the @ sign as well as a . button. Also the auto-correct changes so it doesn’t try to split domain names into multiple words.

It looks like a minor difference but it is very frustrating to enter an email address into a text input on the iPhone. Your users will thank you for paying attention to the details.

Older browsers that don’t understand HTML 5 forms will just fall back to input type=”text”. Which is just fine for our purposes. Also each field has class of “text” so that I can style them with the CSS input.text selector. Even though they aren’t all text fields, I do want them to look the same. You could use CSS3 selectors instead, but getting that to work in IE is beyond the scope of this article.

Adding basic styling.

Now to style our form. We are going to start with a very simple reset. Please use something more appropriate to your project.


/* Add whatever you need to your CSS reset */
html, body, h1, form, fieldset, input {
margin: 0;
padding: 0;
border: none;

body { font-family: Helvetica, Arial, sans-serif; font-size: 12px; }


Now to style the form container.


#registration {
color: #fff;
background: #2d2d2d;
background: -webkit-gradient(
left bottom,
left top,
color-stop(0, rgb(60,60,60)),
color-stop(0.74, rgb(43,43,43)),
color-stop(1, rgb(60,60,60))
background: -moz-linear-gradient(
center bottom,
rgb(60,60,60) 0%,
rgb(43,43,43) 74%,
rgb(60,60,60) 100%
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
margin: 10px;
width: 430px;

#registration a {
color: #8c910b;
text-shadow: 0px -1px 0px #000;

#registration fieldset {
padding: 20px;


Here we are using CSS3 gradients to set the background of the container. We are using three different background declarations to accommodate different browsers. First we set a background color of #2d2d2d that all browsers will understand, then we overwrite it for -webkit and -moz to use background gradients instead. Since Internet Explorer doesn’t understand gradients it will ignore them and use the solid color specified first.

You can use this website to generate your own CSS gradients.

Then for the rounded corners we are adding -webkit-border-radius, then -moz-border-radius for the browsers that support it, then adding standard border-radius for when the official spec is adopted in the future (hopefully by IE9).

For the links we are adding a default color, then more importantly adding text-shadow (not supported in IE). The syntax for the text-shadow is this:


text-shadow: x  y  blur  color;



text-shadow: 0px -1px 0px #000;


So we are using that to add a black vertical shadow that gives the text an indented look.

Styling the Input Fields


input.text {
-webkit-border-radius: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
border:solid 1px #444;
font-size: 14px;
width: 90%;
padding: 7px 8px 7px 8px;
background: #ddd;
background: -moz-linear-gradient(
center bottom,
rgb(225,225,225) 0%,
rgb(215,215,215) 54%,
rgb(173,173,173) 100%
background: -webkit-gradient(
left bottom,
left top,
color-stop(0, rgb(225,225,225)),
color-stop(0.54, rgb(215,215,215)),
color-stop(1, rgb(173,173,173))
text-shadow:0px 1px 0px #FFF;
-moz-box-shadow: 0px 1px 0px #777;
-webkit-box-shadow: 0px 1px 0px #777;
box-shadow: 0px 1px 0px #777;


Here we are adding background gradients again, remember to specify the default for older browsers. The rounded corners also give the fields a nice pill shape.

The new part is that we used a box-shadow to give it a recessed look. The syntax is the same for box-shadow as it is for text-shadow. So box-shadow: 0px 1px 0px #777; is a light colored shadow, with no blur, that is down 1px. This combined with a dark stroke gives it the look below.

Adding Icons.

Next we will add icons to each field so that it is more easily identified at a glance. With CSS3 we are able to use multiple backgrounds to have both a gradient and an image. First create a sprite image of all your icons combined into one file. This will decrease HTTP requests, simplify your markup, and improve page load. An example of the icons I used are on the right.

You will want to replace the earlier code for the input field backgrounds with this new code.


background: #ddd url(‘img/inputSprite.png’) no-repeat 4px 6px;
background: url(‘img/inputSprite.png’) no-repeat 4px 6px, -moz-linear-gradient(
center bottom,
rgb(225,225,225) 0%,
rgb(215,215,215) 54%,
rgb(173,173,173) 100%
background:  url(‘img/inputSprite.png’) no-repeat 4px 6px, -webkit-gradient(
left bottom,
left top,
color-stop(0, rgb(225,225,225)),
color-stop(0.54, rgb(215,215,215)),
color-stop(1, rgb(173,173,173))


We are able to add multiple backgrounds by separating each one with a comma. To accommodate the new icons we will also need to change the right padding to 30px.

padding: 7px 8px 7px 30px;

Then specify the background position for each field individually so that it will display the correct icon. The exact values will depend on the icons that you use. Note that the order of the icons in the sprite does not have to match the order of the input fields.


input#email {
background-position: 4px 5px;
background-position: 4px 5px, 0px 0px;
input#password {
background-position: 4px -20px;
background-position: 4px -20px, 0px 0px;
input#name {
background-position: 4px -46px;
background-position: 4px -46px, 0px 0px;
input#tel {
background-position: 4px -76px;
background-position: 4px -76px, 0px 0px;


Here the first background-position is for the browsers that don’t support multiple background images, the second is for the gradient position on the browsers that do support it.

Styling the Header & Submit Button


#registration h2 {
color: #fff;
text-shadow: 0px -1px 0px #000;
text-align: center;
padding: 18px;
margin: 0px;
font-weight: normal;
font-size: 24px;
font-family: Lucida Grande, Helvetica, Arial, sans-serif;
border-bottom: solid #181818 1px;
-moz-box-shadow: 0px 1px 0px #3a3a3a;
-webkit-box-shadow: 0px 1px 0px #3a3a3a;
box-shadow: 0px 1px 0px #3a3a3a;


Using a bottom border and a box shadow we are able to create an indented separating line without any additional markup.

For the submit button we will use an sprite that has 3 states for :link, :hover, and :active.

You can then use different background positions to shift the image up for each state. This keeps your HTTP requests to a minimum and also prevents a flicker while the browser loads an image for the :hover state.


#registerNew {
width: 203px;
height: 40px;
border: none;
text-indent: -9999px;
background: url(‘img/createAccountButton.png’) no-repeat;
cursor: pointer;
float: right;
#registerNew:hover { background-position: 0px -41px; }
#registerNew:active { background-position: 0px -82px; }


Moving Labels Inline with jQuery.

To further style the forms I want to move the label inside the field itself. This technique is largely based on the work from Trevor Davis at Viget Labs.


<script type="text/javascript">

$(document).ready(function() {
* In-Field Label jQuery Plugin
* Copyright (c) 2009 Doug Neiner
* Dual licensed under the MIT and GPL licenses.
* Uses the same license as jQuery, see:
* @version 0.1
(function($) { $.InFieldLabels = function(label, field, options) { var base = this; base.$label = $(label); base.$field = $(field); base.$"InFieldLabels", base); base.showing = true; base.init = function() { base.options = $.extend({}, $.InFieldLabels.defaultOptions, options); base.$label.css(‘position’, ‘absolute’); var fieldPosition = base.$field.position(); base.$label.css({ ‘left': fieldPosition.left, ‘top': }).addClass(base.options.labelClass); if (base.$field.val() != "") { base.$label.hide(); base.showing = false; }; base.$field.focus(function() { base.fadeOnFocus(); }).blur(function() { base.checkForEmpty(true); }).bind(‘keydown.infieldlabel’, function(e) { base.hideOnChange(e); }).change(function(e) { base.checkForEmpty(); }).bind(‘onPropertyChange’, function() { base.checkForEmpty(); }); }; base.fadeOnFocus = function() { if (base.showing) { base.setOpacity(base.options.fadeOpacity); }; }; base.setOpacity = function(opacity) { base.$label.stop().animate({ opacity: opacity }, base.options.fadeDuration); base.showing = (opacity > 0.0); }; base.checkForEmpty = function(blur) { if (base.$field.val() == "") { base.prepForShow(); base.setOpacity(blur ? 1.0 : base.options.fadeOpacity); } else { base.setOpacity(0.0); }; }; base.prepForShow = function(e) { if (!base.showing) { base.$label.css({ opacity: 0.0 }).show(); base.$field.bind(‘keydown.infieldlabel’, function(e) { base.hideOnChange(e); }); }; }; base.hideOnChange = function(e) { if ((e.keyCode == 16) || (e.keyCode == 9)) return; if (base.showing) { base.$label.hide(); base.showing = false; }; base.$field.unbind(‘keydown.infieldlabel’); }; base.init(); }; $.InFieldLabels.defaultOptions = { fadeOpacity: 0.5, fadeDuration: 300, labelClass: ‘infield’ }; $.fn.inFieldLabels = function(options) { return this.each(function() { var for_attr = $(this).attr(‘for’); if (!for_attr) return; var $field = $("input#" + for_attr + "[type=’text’]," + "input#" + for_attr + "[type=’password’]," + "input#" + for_attr + "[type=’tel’]," + "input#" + for_attr + "[type=’email’]," + "textarea#" + for_attr); if ($field.length == 0) return; (new $.InFieldLabels(this, $field[0], options)); }); }; })(jQuery);

$("#RegisterUserForm label").inFieldLabels();



The line “$(“#RegisterUserForm label”).inFieldLabels();” is what activates the script for those particular labels. Make sure to change the ID if yours is different. I modified the script to add support for the input types “tel” and “email”. If you choose to use others you will need to write those in (near the end of the script).

We are also adding a class of .infield to the labels that need to be restyled. This way if JavaScript is disabled the form will degrade gracefully. Here is the necessary CSS:


fieldset label.infield /* .infield label added by JS */ {
color: #333;
text-shadow: 0px 1px 0px #fff;
position: absolute;
text-align: left;
top: 3px !important;
left: 35px !important;
line-height: 29px;

Sometimes the browser auto-complete can interfere with the inline form fields (especially on login boxes). If this is an issue for your site then you can add autocomplete=”off” to the input fields.

Note: We could have used the HTML5 Placeholder attribute instead, but this method works better in older browsers and also I like how it looks better.

How it looks in Internet Explorer

Because we designed first for modern browsers, certain less capable browsers will not be able to display the form in its best possible look. Here is what IE users will see:

Not as pretty, but everything still functions perfectly.

That’s all!

Please ask any questions and give feedback in the comments.

View Demo Download Code

How We Switched Twitter Usernames

A big part of changing names from WP Limits to Legend Themes was switching the Twitter account. I am never sure how much of a connection your Twitter followers actually have with a specific account. Would they notice if an account suddenly switched names? How much notice should you give?

Acquiring the New Name.

Once deciding on a new domain name I set out to find a Twitter username. It was quite surprising that the domain name was available, but @LegendThemes was not. Luckily I was able to contact the owner and negotiate a reasonable purchase price of $60. Because a Twitter account is free at first it seemed very foreign to pay for it (my wife’s response was “You paid how much for something that is normally free?”), but I think having the right name (especially at that price) is definitely worth it.

Have a Backup Option.

While I wasn’t sure if I could get @LegendThemes I checked every variation and @ThemeLegend was the only acceptable option available. This was quick to save by creating a new twitter account. I waited to announce anything on Twitter until I found out if I could buy my preferred choice.

Once I had the login information for the new account (after paying for it, of course) I made sure to change the email address and password, so that the account was fully in my control. Since Twitters password recovery option is through email it is very important that you change the email address.

Making the Switch.

On the @WPlimits account I made several posts, before and after, to let followers know I would be switching it over to the new name. Wait a while to give anyone time to respond. Then go into the newly purchased account and change the username. I just change it to @legendthemes2, then logged back into @wplimits and changed it to @LegendThemes. Simple.

Technically someone could have stolen the account for the 30 seconds it was exposed, but they would a) have to care about it, and b) know exactly when I was making the switch. Not much of a concern.

From there update the profile image and change the background (if needed), and the important part is done!

Final Details.

Because I didn’t want to lose any users and wanted to minimize any confusion I setup a new account at the now available @WPlimits which pointed to @LegendThemes. I also updated the @ThemeLegend profile to point users in the correct direction as well. The point is to just tie up any possible loose ends.

Have you ever had to switch Twitter usernames? Share your story or thoughts in the comments.

Top Sites for WordPress Information

This is the series of sites that I subscribe to in order to keep up on WordPress news and to always get better at working with WordPress.

WordPress Development & Announcements

  • Official WordPress Blog
    Jane Wells provides great updates on the development status, any new features being released, and also where you can jump in to help the project.
  • WordPress UI
    The WordPress UI group works here to discuss improvements to the software that are user interface related. You can get involved with the UI IRC chat on Thursdays at 2:00 PM Eastern.
  • WordPress Dev
    From here you can follow the status of the latest WordPress development projects. You can get involved with the main WordPress development IRC chat on Thursdays at 3:30 PM Eastern.
  • Matt’s Blog
    The founders blog is always a good place to stay up on WordPress announcements, plus he is a very interesting entrepreneur.
    The official site & forums for BuddyPress development. If you aren’t already using BuddyPress for a project you should be as it no longer requires an installation of WordPress MU.

Tips & Tutorials

  • Smashing Magazine on WordPress
    Smashing always puts out high quality articles and their WordPress posts are no exception.
  • NetTuts on WordPress
    Envato has a great section on working with WordPress, not updated too often, but definitely worth subscribing too.
  • WP Engineer
    Here you can get more technical tips as well as great previews for what is coming in the next version of WordPress.
  • WP Recipes
    Jean-Baptiste Jung’s blog on WordPress tips and tricks. He has some of the best simple tips to help you customize your WordPress blog.
  • Justin Tadlock
    I learned all about custom taxonomies and other great ideas from Justin. His blog is a must read for an advanced WordPress developer.
  • WP Candy
    This site hasn’t been updated lately, which is a shame, because their old content is really good and helpful.
  • Theme Shaper
    Ian Stewart is the creator of the Thematic framework and the Kirby theme which is the foundation of the new WordPress default theme 2010. His blog is great for tips and WordPress news.

WordPress MU

    Though mostly focused on WordPress MU, they have recently branched out to standard WP tips as well as lots of great resources on BuddyPress.
  • WPMU Tutorials
    Andrea and Ron are two of the most helpful members of the WordPress community. Their blog on WordPress multi-user is a must read!

There are many more WordPress tutorial sites out on the web that I didn’t list here. This is just the collection that I find valuable on a day-to-day basis. If you have suggestions of sites I should add let me know in the comments.

Our blog will regularly be updated with WordPress tips, theme announcements, and general news. Subscribe to our RSS feed to stay updated.

Get WordPress Tips Through Twitter!

We just launched a WP Limits Twitter account. It will feature short (140 characters or less!) tips on WordPress or links to other great articles. Don’t worry, we won’t update more than once per day, so we won’t be spamming your account. Lots of great resources coming!

Make sure to follow the account here:

If you have any ideas to contribute we would greatly appreciate it as well!

WordCamp, Carrington Theme, and Great Design

Over the weekend I was able to go to WordCamp Utah and hear some great talks. I will have a more detailed write-up coming soon. Our weekly resources post will feature a lot of information from those talks.

  1. WordCamp Utah Video Stream
    This has all of the videos from the conference. In particular check out Matt’s keynote address and Cameron’s talk on design. By far the best.
  2. Good vs. Great Design
    Cameron Moll is a great designer and very well polished speaker. He has a lot of things to say on the topic of design, and being a great designer. The link is to his slide deck for the talk. You can view the video on the uStream channel linked to above.
  3. Carrington Theme
    Announced by Alex King of CrowdFavorite during his talk at WordCamp, Carrington is a new kind of theme. Or rather more of a theme framework. They have a lot of great features and an interesting new approach to theme development. Here is what Matt says about it:

Themes, Default Content, WP Coder, and Widgets

  1. How to Create a WordPress Theme From Scratch (Part 2) –
    Earlier we posted a link to creating a WordPress theme from scratch. Here is the next part in that great tutorial.
  2. Easier Theme Development with Sample WordPress Content –
    Want to thoroughly test your theme for every situation? This post details how you can create sample content to make sure that your theme covers every angle.
  3. WP Candy Launches WP Coder –
    As a bit of community news, the people behind WP Candy have launched WP Coder, a new PSD to WordPress conversion site. There prices look pretty good. If nothing else, the site design is worth looking at!
  4. Create a Widget Ready Footer in WordPress -
    Widgets are powerful. Too often people don’t use them to their full potential. Take a look at this post to learn a new way to use them in your footer.
  5. Displaying WordPress Categories as a Drop Down Menu -
    Often for a good magazine layout instead of using pages, you will use categories. This post shows how to create that navigation.

Navigation Tips: Suckerfish, Sliding Doors, and Breadcrumbs

  1. Sliding Doors Navigation with WordPress
    WordPress by default cannot support the infamous sliding doors technique, but with this simple change, you can create beautiful navigation to your hearts content.
  2. Sliding Doors + Sons of Suckerfish
    Last week we talked about Sons of Suckerfish and how to use them in a WordPress blog. Now we have an article detailing using sliding doors and Sons of Suckerfish (though this article is not WordPress specific).
  3. Breadcrumb Navigation for Categories
    A lot of magazine sites use categories as the main navigation to better separate content. We all know that for both SEO and usability breadcrumbs make a huge difference, so why not add them in for categories as well as pages? This article shows you how.
  4. Tips on Writing WordPress Tips
    Want to have your WordPress related content featured on mainstream blogs? Well, here is a list of the criteria to follow to make that happen. It is a great list on what mistakes to avoid when writing your WordPress tips.

Archives, Comments, Jabs, and Theme Design

  1. Beautiful Website Archives
    A great article by Apple designer and CSS guru Jina Bolton on some innovative and great archive pages. Too often WordPress theme designers don’t pay attention to the details of the theme like archives, so this should serve as some inspiration to rethink your archives pages. Leaving it to default styling is for beginners.
  2. Hack Together a User Submitted Comments Feed
    Here at WP Limits we are always looking for innovative ways to push the limits of WordPress. Well, Collis over at Envato has done exactly that. Take a look!
  3. Woo Themes Takes a Jab at WP Designer
    You won’t find a great tip or tutorial here, but if you have been following the WordPress community you are no doubt familiar with the untimely death of This ad from Woo Themes is taking advantage of that.
  4. Creating a WordPress Theme from Scratch
    NetTuts shows us how to create a very basic WordPress theme. It is probably the fastest introduction I have ever read.
  5. Designing for WordPress: Complete Series
    Looking for something more in depth then the last link? Well, then this is for you. There is a lot of content there (so much that I am going to end my weekly list right here), so take some time and really learn how to create a theme.

7 Links to Launch the Site

It’s Monday and to celebrate the launch of a great new blog, we are linking to some excellent posts on other blogs we enjoy reading.

  1. We Love WordPress
    Having trouble thinking of what can be done with WordPress? Well, here is a great gallery of pure WordPress sites. Enjoy!
  2. How Simple Web Design Helps Your Business
    Yes, most of what we will be writing on is WordPress specific, but this post is too good to pass up. If you use WordPress as a CMS in anyway, then you should read this post regarding businesses.
  3. Creating Two-Tiered Conditional Navigation in WordPress
    Navigation is key to any blog or website, now if you have a lot of content (which WordPress is great at!) then navigation is crucial. Here is one way to do it well.
  4. 30 Free High Quality WordPress Themes
    There are some really original themes in this bunch. As always Smashing Magazine has great lists of designs.
  5. Unraveling the Secrets of WordPress’ Comments.php File -
    This is the most detailed explanation of WordPress theme code I have found yet. By the time you finish reading this you will know everything possible about styling comments!
  6. Does WordPress Scare Your Clients
    This is a great ongoing discussion on using WordPress as a CMS for clients, and how they react to it. If you currently use it on client sites, or are considering it for such a use, read the article and the discussion, it may help you answer a lot of questions before your clients even ask them.
  7. WP Screen Casts -
    If you need to easily teach someone the WordPress backend, then there is no easier way to do it then with screen casts. Send these to a client and possibly save having to sit down with them to teach them how to write a post. Definitely worth checking out.