Copy hi@ste․digital
Posted on

How to Create a Contact Form using HTML5, CSS3 and PHP

Personally, I feel it is important to be aware of the [positive] impact HTML5 will have on forms and the way they will function in years to come. Realistically, we can’t implement all of the new features today, but you don’t want to be lagging behind the rest of the industry when these features finally become widely supported.

Having said that, this tutorial will be focusing on the new HTML5 features that are already supported by all the major browsers, or that at least employ graceful degradation for the browsers that are still trying to play catch up.

1. The Design

First of all, this is not a Photoshop tutorial. I have designed the look of the form, but we’re going to be focusing on replicating it using the latest coding techniques and making it function correctly.

Form design

2. The HTML5 Markup

Now we have a design to work towards, we’re going to form the structure of the contact form using HTML5. Firstly, open up a new PHP file and save it as index.php (or your-page-name.php). Now, because we need to use PHP to make the form function, you will need access to a web server in order to test your code. Ideally, you could set up your own machine as a server using Xampp; alternatively, if you have some online hosting space, you could use that, however this method means you will have to re-upload the files whenever you want to test them.

Doctype

Okay, now we’ve got our blank PHP document, let’s start with the appropriate doctype, which is a lot simpler in HTML5 than previous versions to say the least!

<!DOCTYPE HTML>
<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Contact Form</title>
</head>

<body>
</body>

</html>

Yep, that’s right. There’s no horrible combination of letters and numbers to remember for the HTML5 doctype. Just simply; <!DOCTYPE HTML>.

Just to compare, here’s the doctype for XHTML; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">.

I get the feeling we have a clear winner here? I think this sets the precedent for HTML5, as many of the new tags and attributes represent a simplified method of doing the things that used to take twice the amount of code or several lines of JavaScript.

Structure

The next step is to code the basic structure of the page, so we need to take a look at the design and divide it into logical sections.

The form structure

So, we have a header section, a content section and a footer section. All very simple right? Yes, but with HTML5, it’s even simpler. And much more semantic too.

<!DOCTYPE HTML>
<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Contact Form</title>
</head>

<body>

    <header class="body">
    </header>

    <main class="body">
    </main>

    <footer class="body">
    </footer>

</body>

</html>

That’s right. No divs. HTML5 has introduced new tags that actually have real meaning and purpose, much more semantic than simply using divs all over the place. I’ve also given each of these elements a class of ‘body’ to show that they are part of the main content body and can be styled as such. You could of course achieve this with a div wrapper, but with only a few main body elements, it’s just as easy to assign classes in this case.

The Form

It’s about time we got onto the Contact Form, right? Obviously, the markup for the form will go within the <main> tags.

<form>
        
    <label>Name</label>
    <input name="name" placeholder="Type Here">
            
    <label>Email</label>
    <input name="email" type="email" placeholder="Type Here">
            
    <label>Message</label>
    <textarea name="message" placeholder="Type Here"></textarea>
            
    <input id="submit" name="submit" type="submit" value="Submit">
        
</form>

So that’s the form markup, now to explain a few things.

Input Tag

You may have noticed that the input tags work slightly differently to XHTML, where they are closed using the forward-slash character; <input />. In HTML5, this tag has again, been simplified to just <input>.

Input Name

All of the <input> tags also have the name attribute declared. This comes into play later on when we create the PHP script that will handle the form data.

Input Type

The type attribute has seen some major improvement in the transition from XHTML to HTML5. Unfortunately, most of the new <input> types can’t realistically be used as of yet due to minimal support, but it’s nice to know that they will make our jobs a lot easier in years to come.

There are however, certain <input> types that we can use, and see the benefits of right now – however small these benefits might be. I have included type="email" in this tutorial, because there is no downside to employing it – there are only positives. It may not be anything mind-blowing, but it’s worth implementing, as any browsers that don’t support this new input type, simply recognise it as type="text". And on the iPhone, this <input> type causes a modified keyboard to appear when the email field is selected, which includes a reduced space bar and the @ symbol takes centre focus.

ios keyboard for email input type

Placeholder Attribute

<input> attributes are another area of major innovation in HTML5, allowing developers to achieve things that were previously only possible through the use of several lines of JavaScript. The particular one we’re using is the placeholder attribute, which is reasonably well supported in the most recent browser releases. It allows you to assign a value to a text field, which when selected, disappears and, if no text has been entered, will reappear again when de-selected. I’ve used this idea for a long time now, but it’s always used some bulky, ugly JavaScript code to make it work.

Input placeholder

3. The CSS

After having wrote the markup for the page, this is the result…

Unstyled form

Not very pretty is it? This is where we can use some CSS to spruce things up a bit and make it look closer to the original design. Firstly, let’s give the form a more familiar feel by making it read top to bottom rather than left to right.

label {
    display:block;
    margin-top:20px;
    letter-spacing:2px;
}

Giving the label elements a property and value of display:block; allows them to behave like a block level element, thus forcing the text boxes down onto the next line. I’ve also applied a couple of other self-explanatory properties for spacing and aesthetic purposes.

Structural styling

Next, we need to centre the page and the form, and we’re going to style the <input> boxes, after which we will really start to see the page transform.

/* Centre the page */
.body {
    display:block;
    margin:0 auto;
    width:576px;
}

/* Centre the form within the page */
form {
    margin:0 auto;
    width:459px;
}

/* Style the text boxes */
input, textarea {
	width:439px;
	height:27px;
	background:#efefef;
	border:1px solid #dedede;
	padding:10px;
	margin-top:3px;
	font-size:0.9em;
	color:#3a3a3a;
}

textarea {
	height:213px;
	background:url(images/textarea-bg.jpg) right no-repeat #efefef;
}

All of the above is pretty standard CSS; applying a width to the elements with the .body class as well as margin:0 auto; will centre the page, and the same technique centres the form within the page.

The input and textarea elements share many of the same CSS values, but there are a couple of properties that differentiate the main message text box from the text fields. Obviously the textarea requires much more height, but we’re also applying a very subtle background image to this element. To do this we simply state the image source and position it correctly by setting the other background values to right and no-repeat.

Styled fields

Okay, now we can add the finishing touches to the text boxes with a bit of CSS3.

input, textarea {
    width:439px;
    height:27px;
    background:#efefef;
    border:1px solid #dedede;
    padding:10px;
    margin-top:3px;
    font-size:0.9em;
    color:#3a3a3a;
    -moz-border-radius:5px;
    -webkit-border-radius:5px;
    border-radius:5px;
}

You can see that we have added three new lines to our CSS which will render rounded corners in all major browsers… except of course for Internet Explorer 8 and below. The standard border-radius property will work in Opera, the -webkit prefix works for Chrome and Safari and the -moz prefix renders rounded corners in Firefox.

One last thing to address regarding the text boxes is to assign them a very subtle :focus state in order to provide some visual feedback to the users actions. This, once again, couldn’t be simpler.

input:focus, textarea:focus {
    border:1px solid #97d6eb;
}

You can see that we have just given the <input> and <textarea> elements a subtle blue border when they are currently selected.

Input fields with focus style

Finally, we’re going to create our custom submit button. The submit button is an <input> element, so we gave it its own id="submit" in order to override some of the CSS we had already assigned to <input> elements, as shown below.

#submit {
    width:127px;
    height:38px;
    background:url(images/submit.jpg);
    text-indent:-9999px;
    border:none;
    margin-top:20px;
    cursor:pointer;
}

#submit:hover {
    opacity:.9;
}

Firstly, we assign the appropriate width and height of the button, before setting its background image to the button we created in the design. The text-indent:-9999px; line is a little trick to hide the actual ‘Submit’ text from the button and simply display the background image.

Finally, we assign the button a :hover state, within which we’ve utilised another little aspect of CSS3 in the form of the opacity property, which is widely supported across the major browsers, except from… yep, you’ve guessed it.

4. Making the form function with PHP

First things first, we need to revisit the HTML so we can add a couple of bits that will allow the form to communicate with the PHP script.

<form method="post" action="index.php">
        
    <label>Name</label>
    <input name="name" placeholder="Type Here">
            
    <label>Email</label>
    <input name="email" type="email" placeholder="Type Here">
            
    <label>Message</label>
    <textarea name="message" placeholder="Type Here"></textarea>
            
    <input id="submit" name="submit" type="submit" value="Submit">
        
</form>

So what’s been added? Take a look at the opening <form> tag. We’ve added two new attributes; method and action.

The method="post" attribute provides the PHP script with a method of extracting the values from the form, so the script can then do what it wants with those values. The action="index.php" attribute simply tells us the location of the PHP script; in this case, because it’s only a few lines of code, we’re going to insert it just above the form in our index.php file. So when the form is submitted, it will go to index.php and find the script.

Take another look at the HTML above and you will see that each of the form elements have the name attribute. The PHP uses this attribute to extract the data from each of the form elements. Let’s look at how it does this…

<?php
    $name = $_POST['name'];
    $email = $_POST['email'];
    $message = $_POST['message'];
?>

If you’ve never used PHP before, it might look a bit confusing – but it’s actually really simple. The $_POST part is a built in PHP function which is used to collect data from a form that uses method="post" like ours does. The part that immediately follows this function, ['name'] must correspond to the name attribute from the form input; in the first instance, name="name"!

So, this will collect whatever data has been entered into the name field – now we need something to store that data in. This is where variables come into play. In this case, $name is the variable that we will use to store the data from the name field. We can then do the same for the email and message fields. Simple!

Now, we’re going to add a few more variables that the form requires in order to function.

<?php
    $name = $_POST['name'];
    $email = $_POST['email'];
    $message = $_POST['message'];
    $from = 'From: TangledDemo'; 
    $to = 'demo@tangledindesign.com'; 
    $subject = 'Hello';
?>

These new variables determine the destination of the email, the subject field and where the email has come from. In the next step, we will be storing all of the data from the form in one variable in order to simplify things a little.

<?php
    $name = $_POST['name'];
    $email = $_POST['email'];
    $message = $_POST['message'];
    $from = 'From: TangledDemo'; 
    $to = 'demo@tangledindesign.com'; 
    $subject = 'Hello';

    $body = "From: $name\n E-Mail: $email\n Message:\n $message";
?>

You can see from the above snippet that we have taken the variables we declared previously and have now stored them all in one variable called $body, which will be the actual content of the email.

It’s almost time to use the mail() function to actually send the email! But first, we need to explain how this function is only performed when the form is submitted and not every time the user loads index.php.

<?php
if ($_POST['submit']) {
    /* Anything that goes in here is only performed if the form is submitted */
}
?>

Basically, any code inside the above if statement will only be performed once the submit button has been pressed. Again, the ['submit'] part must correspond to the name of the submit button in your form.

Now we can go ahead and use the mail() function.

<?php
if ($_POST['submit']) {
    if (mail ($to, $subject, $body, $from)) { 
        echo '<p>Your message has been sent!</p>';
    } else { 
        echo '<p>Something went wrong, go back and try again!</p>'; 
    }
}
?>

The mail() function is a built in PHP function that actually performs the task of sending the email to the appropriate recipient. The above code uses an if statement, which basically states that if the mail function is performed correctly, then tell the user the message has been sent; if the mail function didn’t perform correctly, then notify the user that there has been a problem.

Now, if you test the form on your server you should find that it works correctly! The best way to ensure the form is working is to upload it to an online server and set the recipient email address as an email hosted on the same server.

Note that you can place this script wherever you want the confirmation message to appear. For example, if you want the message to appear above the form as it does in the demo, then you simply place the PHP script directly above the form, NOT in a separate PHP file.

Spam Prevention

Before we finish off, we’re going to look at a very simple method of spam prevention. To begin this process we must once again revisit the HTML and add in one more <input> element to our form. We’re going to insert this element just before the submit button.

<label>*What is 2+2? (Anti-spam)</label>
<input name="human" placeholder="Type Here">

Now back to the PHP, we need to use the POST method to extract whatever the user has entered into this field. Because we gave the element a name of “human”, we add the following line to our PHP; $human = $_POST['human'];.

Remember the PHP if statement we used to carry out functions only once the form had been submitted? Well we’re going to need to slightly modify that statement now.

<?php
if ($_POST['submit'] && $human == '4') {
    if (mail ($to, $subject, $body, $from)) { 
        echo '<p>Your message has been sent!</p>';
    } else { 
        echo '<p>Something went wrong, go back and try again!</p>'; 
    }
}
?>

The statement now requires that the value of ‘human’ (the response to the anti-spam question) must be ‘4’ in order for the mail function to be carried out. Now we need to add one last bit of code to let the user know if they have answered the anti-spam question incorrectly.

<?php
if ($_POST['submit'] && $human == '4') {
    if (mail ($to, $subject, $body, $from)) { 
        echo '<p>Your message has been sent!</p>';
    } else { 
        echo '<p>Something went wrong, go back and try again!</p>'; 
    }
} else if ($_POST['submit'] && $human != '4') {
    echo '<p>You answered the anti-spam question incorrectly!</p>';
}
?>

We have added to our if statement by using else if, which in this case states that if the form has been submitted and the answer to the anti-spam question was not ‘4’, then do not perform the mail() function and notify the user that their answer was wrong.

And that… is that! The Final PHP code can be found below. Thanks for reading. If you read it all – good effort! And let me know how you got on by leaving a comment below.

<?php
    $name = $_POST['name'];
    $email = $_POST['email'];
    $message = $_POST['message'];
    $from = 'From: TangledDemo'; 
    $to = 'demo@tangledindesign.com'; 
    $subject = 'Hello';
    $human = $_POST['human'];
			
    $body = "From: $name\n E-Mail: $email\n Message:\n $message";
				
    if ($_POST['submit'] && $human == '4') {				 
        if (mail ($to, $subject, $body, $from)) { 
	    echo '<p>Your message has been sent!</p>';
	} else { 
	    echo '<p>Something went wrong, go back and try again!</p>'; 
	} 
    } else if ($_POST['submit'] && $human != '4') {
	echo '<p>You answered the anti-spam question incorrectly!</p>';
    }
?>

Update

One or two people have asked about making the form work with required fields. Here’s the script you’d need if the name and email fields in my example were both required fields…

if ($_POST['submit']) {
    if ($name != '' && $email != '') {
        if ($human == '4') {				 
            if (mail ($to, $subject, $body, $from)) { 
	        echo '<p>Your message has been sent!</p>';
	    } else { 
	        echo '<p>Something went wrong, go back and try again!</p>'; 
	    } 
	} else if ($_POST['submit'] && $human != '4') {
	    echo '<p>You answered the anti-spam question incorrectly!</p>';
	}
    } else {
        echo '<p>You need to fill in all required fields!!</p>';
    }
}

Further Reading

Dive into HTML 5 – Forms
nettuts – Rethinking Forms in HTML5
W3C Working Draft – Forms in HTML5