Full CSS3 HTML5 Contact Form with No Images

In this tutorial, I will show you the code step by step to create a full HTML5 CSS3 contact form like the one above, without using any images. First, a little disclaimer. HTML5 and CSS3 are still working drafts; the goal of this tutorial is to show what we can do with those technologies. This form has some compatibility issues with old browsers, so if you want to use it in production, do so at your own risks.

The form we will build is a simple contact form with basic information: name, email, URL, subject and message.

Full CSS3 HTML5 Contact Form with No Images


For the sanity of the code, I omitted the vendor prefixes in this article, but you will find them in the complete file (or by viewing the source code of the example)

Final Product

HTML5 New Form Elements

HTML5 specs introduce many new form elements to enhance form functionalities. For this tut, here are the ones we will use in our form:

  • Input type = email can be used when user needs to enter an email address. Browsers that support it will be able to detect if what the user entered was an email address or not.
  • Input type = url can be used to check if the user entered a correct and valid URL.
  • Autocomplete = on attribute can be placed either on the form, or on single inputs. When autocomplete = "on", if the a user has already completed a form, the autocomplete attribute enables him to find what he already entered.
  • Require = required attribute sets the state of a form element as required. For browsers which support it, the user won’t be able to send the form until all the required fields have been completed. By default the user can’t see required fields until he submits the form, so the web designer still has to add a visual indication.
  • Placeholder this attribute represents a short hint so that the user knows what he can enter as data, for example the format for email. The placeholder disappears when the user clicks on the field, and reappears when the cursor is moved and the field is still empty.

Now that you are more familiar with the new elements, let’s see the HTML code for our nice little form :

<div id="content">
<h1> Contact me </h1>

<form action=" " method="post"  autocomplete="on">
<p> <label for="username" class="iconic user" > Name <span class="required">*</span></label> <input type="text" name="username" id="username"  required="required" placeholder="Hi friend, how may I call you ?"  /> </p>

<p> <label for="usermail" class="iconic mail-alt"> E-mail address <span class="required">*</span></label> <input type="email" name="usermail" id="usermail" placeholder="I promise I hate spam as much as you do" required="required"  /> </p>

<p> <label for="usersite" class="iconic link"> Website </label> <input type="url" name="usersite" id="usersite"  placeholder="e.g.: http://www.miste.com" /> </p>

<p> <label for="subject" class="iconic quote-alt"> Subject </label> <input type="text" name="subject" id="subject"  placeholder="What would you like to talk about?" /> </p>

<p> <label for="message" class="iconic comment"> Message  <span class="required">*</span></label> <textarea placeholder="Don't be shy, live me a friendly message and I'll answer as soon as possible "  required="required" ></textarea> </p>

<p class="indication"> All fields with a <span class="required">*</span> are required</p>

<input type="submit" value=" ★  Send the mail !" />      
</form>                             
</div>           

Naked Form

Not many ids or classes, the goal here is to use as less HTML as possible and to use CSS3 to style the form. And don’t forget to use the HTML5 doctype !

Creating the Striped Background

Let's start with general layout and let's give this form a background.To create the striped border, we will only style one element : #content. The idea here is pretty simple : we will create a full striped background on this element using CSS3 gradients like this :

#content{
position:relative;
margin:50px auto;   
width:400px;
min-height:200px;
z-index:100;
padding:30px;
border:1px solid #383838;   
background: #D1D1D1;
/* My stripped background */
background: repeating-linear-gradient(-45deg, #EFC1CB , #EFC1CB 30px, #F2F2F2 30px, #F2F2F2 40px, #C2E8F5 40px, #C2E8F5 70px,#F2F2F2 70px, #F2F2F2 80px);
border-radius:8px;
box-shadow:0px 1px 6px #3F3F3F;
}

Let’s take a closer look at our gradient : background: repeating-linear-gradient(-45deg, #EFC1CB , #EFC1CB 30px, #F2F2F2 30px, #F2F2F2 40px, #C2E8F5 40px, #C2E8F5 70px,#F2F2F2 70px, #F2F2F2 80px);.

Putting this in words, here is what we are doing : create a linear gradient with a 45° angle, the first stripe is a pink one, that goes from 0 to 30px, then add a grey one from 30 to 40px, and a blue one from 40 to 70px, and finish with another grey one from 70 to 80px. Repeat the whole gradient. Doing this, we create a 45° striped "gradient" with a 30px pink line, a 10px grey one, a 40px blue one, and a 10px grey one.

Stripped Background

Now that we have our gradient background, we will cheat, remember we want a border. All we have to do, is position a new container on the top of it, with another color. We don’t want to add unnecessary spans or divs, so we will use a pseudo class :after to do the trick :

/** my "fake" background that will hover the stripes **/
#content:after{
background:#F9F9F9;
margin:10px;
position: absolute;
content : " ";
bottom: 0;
left: 0;
right: 0;
top: 0;
z-index: -1; 
border:1px #E5E5E5 solid;       
border-radius:8px;
}

The "size" of our border is here controlled by the margin of the after element. Remember to use enough padding on #content so that your content will actually be "inside" the after fake background.

Styling H1 and Text Font

For the h1, I chose the Questrial font, for the body the Droid Sans and the ampersand will use the Alice font. Those are Google font directory fonts, so all I have to do is use the Google font api code in my header like this, one http request to style them all :

<link href='http://fonts.googleapis.com/css?family=Questrial|Droid+Sans|Alice' rel='stylesheet' type='text/css'>

Header

I applied the droid sans to the body, and the questrial to the h1. For the h1 decoration, we will again use the :before :after tricks :

h1 {
font-family: 'Questrial', Verdana, sans-serif;
text-align:center;
font-size:40px;
padding:0;
margin:0 0 20px 0;
position:relative;
color:#8C8C8C;
}

/** have a nice ampersand **/
h1:after {
font-size:25px;
color:#D6CFCB;
content: '&';
text-align:center;
display:block;
width:100%;
font-family: 'Alice', Verdana, serif;
text-shadow: 0px 1px 0px #fff;
}

/** create the gradient bottom **/
h1:before {
position:absolute;
bottom:15px;
content: ' ';
text-align:center;
display:block;
height:2px;
width:100%;
background: linear-gradient(left,  rgba(255,255,255,0) 0%,rgba(182,180,180,0.7) 42%,rgba(180,178,178,0) 43%,rgba(168,166,166,0) 50%,rgba(180,178,178,0) 57%,rgba(182,180,180,0.7) 58%,rgba(238,237,237,0.3) 90%,rgba(255,255,255,0) 100%); /* W3C */
}

Adding the Little Icons, with No Images

Here comes the good trick, I’m sure you are wondering "she said there will be no images, how did she add those little icons?". The trick is quite simple, we will be using an icon font. For those who are not familiar with the concept, it consists of mapping each letter of the alphabet with an icon, and creating a font using those icons. An interesting article by Chris Coyer from csstricks should help you get a better understanding of how this works.

Icons

Credit where due, for this demo we will be using the awesome icon font by P.J. Onori called iconic.

Here is the code, again, we will use the :before trick you’re getting used to it.

/** adding our icon font !! */
@font-face {
font-family: 'IconicStroke';
src: url('font/iconic_stroke-webfont.eot');
src: url('font/iconic_stroke-webfont.eot?#iefix') format('embedded-opentype'),
url('font/iconic_stroke-webfont.woff') format('woff'),
url('font/iconic_stroke-webfont.ttf') format('truetype'),
url('font/iconic_stroke-webfont.svg#IconicStrokeRegular') format('svg');
font-weight: normal;
font-style: normal;
}

.iconic:before{
font-size:25px;
font-family: "IconicStroke";
}
.iconic.link:before { content: '/'; }
.iconic.quote-alt:before { content: "'"; }
.iconic.comment:before { content: "q"; }
.iconic.user:before { content: "u"; }
.iconic.mail-alt:before { content: "M"; }

We first apply the iconic font to all our “icons” and then, use letters associated with the icon. The idea of using a before, is that this is pure non semantic styling, so the letters won’t add any non semantics in the html code.

Here we can use the icon font since we still have the label in plain text, so it’s basically just eyecandy and won’t trigger usability issues : form will still be readable even if the font won’t load.

Styling our Fields, the Power to Say :not()

As I said in the introduction, we want to use as little HTML as possible, so no ids. To format our inputs, we could trigger them one by one, using input[type= text, email …]. But CSS3 gives us a quicker, cleaner solution, the :not().We want all our inputs to look the same except the submit button, so we can use this : input:not([type="submit"]).

Not

Here is the code, comments should help you understand each part

/** we remove the red glow around required fields since we are already using the red star */
input:required, textarea:required {
-moz-box-shadow:none; 
-webkit-box-shadow:none; 
-o-box-shadow:none; 
box-shadow:none; 
}
/** inputs and textarea**/
input:not([type="submit"]),
textarea{
outline:none;
display:block;
width:380px;
padding:4px 8px;
border:1px dashed #DBDBDB;
color:#3F3F3F;
font-family:'Droid Sans',Tahoma,Arial,Verdana sans-serif;
font-size:14px;
border-radius:2px;
transition:background 0.2s linear,
box-shadow 0.6s linear;
}
input:not([type="submit"]):active,
textarea:active,
input:not([type="submit"]):focus,
textarea:focus{
background:#F7F7F7;
border:dashed 1px #969696;
box-shadow:2px 2px 7px #E8E8E8 inset;
}
input:not([type="submit"]){
height: 20px;
}
textarea{
min-height:150px;
resize:vertical
}
/* placeholder */
::-webkit-input-placeholder  {
color:#BABABA;
font-style:italic;
}
input:-moz-placeholder,
textarea:-moz-placeholder{
color:#BABABA;
font-style:italic;
}

What we can emphasize here :

  • We removed the browser focus style with outline:none; to add our own focus/active style.
  • We used CSS3 transition to add a nice effect when the field is active. Note that you can use different transitions on different elements with different timings as long as you separate them with commas.
  • We have to use the vendor prefix to style the placeholder. Note that webkit-input-placeholder also works on textareas (bug or not ? good question) but for Mozilla you will have to use a specific one for textareas.
  • Since we are using a red star (see next point) to style the required fields, we will remove the ugly default red glow from browsers.

Time to Style the Send Button!

For the send button, we use an input type=submit, and here, we unfortunately can’t use the :before :after trick, it does not work on such inputs. So I used a special character directly in the HTML. I'm not so proud of this non semantic solution, so you may want to remove it.

Final Form

To style the button, we here again use some gradient goodness, and a little box shadow trick I’ll explain after the code.

/** Styling the send button **/
input[type=submit]{
margin-left:235px;
cursor:pointer;
background:none;
border:none;
font-family: 'Alice',serif;
color:#767676;
font-size:18px;
padding:10px 4px;
border:1px solid #E0E0E0;
text-shadow: 0px 1px  1px #E8E8E8;
background: rgb(247,247,247);
background: linear-gradient(top,  rgba(247,247,247,1) 1%,rgba(242,242,242,1) 100%);
border-radius:5px;
box-shadow:0px 1px 1px #FFF inset,           
0 0 0px 5px #EAEAEA;
transition:all 0.2s linear;
}

input[type=submit]:hover{
color:#686868;
border-color: #CECECE;
background: linear-gradient(top,  rgba(244,244,244,1) 0%,rgba(242,242,242,1) 100%);
box-shadow:0px 1px 1px #FFF inset,
0 0 0px 5px #E0E0E0;       
}

input[type=submit]:active,
input[type=submit]:focus{
position:relative;
top:1px;
color:#515151;
background: linear-gradient(top,  rgba(234,234,234,1) 0%,rgba(242,242,242,1) 100%);
box-shadow:0px -1px 1px #FFF inset,
0 0 0px 5px #E0E0E0;
}

The button is composed of a very light gradient, a 1px white inset box shadow at the top, a first 1px grey border, and a second 5px grey border. I see what you will say "but you can’t apply two CSS borders", and you’re right. That’s where our box-shadow trick comes in. You can set as many box shadows you like using comma.

The trick here is in the sentence "The property is a comma-separated list of shadows, each specified by 2-4 length values" of the specs: you can set a length to the box shadow, and that’s what we do with the 0 0 0px 5px #E0E0E0. We create a box shadow with x and y 0 shadow, a grey color, and a 5px length, thus creating a "fake" second border.

Styling the Labels with Nice Transitions

To finish, we will add some nice colors and transitions to our labels when the user hovers over them.

label{
color:#7F7E7E;
-webkit-transition: color 1s ease;
-moz-transition: color 1s ease;
transition: color 1s ease;
}
label:hover{
color:#191919;
}
label:before{
color:#C1BFBD;
transition: color 1s ease;
}
label:hover:before{
color:#969696;
transition: color 1s ease;
}

p{
margin-bottom:20px;
}
.indication{
color:#878787;
font-size:12px;
font-style:italic;
text-align:right;
padding-right:10px;
}
.required{
color:#E5224C;
}

Here I just wanted to emphasize the fact that you can add many pseudo classes like label:hover:before. For the moment unfortunately the transition on pseudo class will only work on Firefox, so the icon's color will change with no transition on chrome. And that's by the way another goodness of the icon font : you can easily change its color without the need of a sprite for example. Your turn to have fun.

You can now have a little bit of fun with the form, test hover effects, and test the power of the HTML5 new elements. Try to click on send without filling the required fields, or enter an invalid email address to see what happens. I would recommend using Firefox or Chrome latest versions.

Conclusion

I hope this tutorial gave you a better understanding of the future and all possibilities that HTML5 and CSS3 can offer us. I will once again emphasize the fact that this is a demo, for the purpose of playing around with code, and that you should not use it on a live website unless you know what you are doing and use solid fallbacks.

To enhance compatibility, you could for instance detect browser features using modernizr and you can find some useful HTML5 polyfills.

Your turn now: how do you use CSS3 in your projects ? What about HTML5? Add a comment to this article to give us your opinion.