Creating Stylish Responsive Form With CSS3 and HTML5

Coding with CSS3 has dramatically changed the landscape within frontend web development. There are more opportunities to build unique interfaces with gradients, drop shadows and rounded corners. All of these effects are slowly becoming adopted in every major web browser.

In this tutorial I want to showcase many of these cool CSS3 effects. I’ve built a simple web form using some of the newer HTML5 input types. The layout is also responsive; it will adapt as the window size is reduced. This situation is perfect for building web forms to support smartphone users.

Check out the source code and see if you can follow along in the file structure. Also, feel free to customize these elements and copy them into your own websites.

Building the Form Structure

To start I’ve created a main file index.html along with two separate stylesheets. style.css contains all the default selectors while responsive.css handles different window sizes. My doctype is HTML5 and I’ve wrapped the entire form in a container <div>.

This example only demonstrates the effects you can manifest when coding in CSS3. Thus we have no post submission script or destination to redirect the user. My code below contains the opening input tags for our first few form elements.

<form name="hongkiat" id="hongkiat-form" method="post" action="#">
<div id="wrapping" class="clearfix">
	<section id="aligned">
		<input type="text" name="name" id="name" placeholder="Your name" autocomplete="off" tabindex="1" class="txtinput">
		<input type="email" name="email" id="email" placeholder="Your e-mail address" autocomplete="off" tabindex="2" class="txtinput">
		<input type="url" name="website" id="website" placeholder="Website URL" autocomplete="off" tabindex="3" class="txtinput">
		<input type="tel" name="telephone" id="telephone" placeholder="Phone number?(optional)" tabindex="4" class="txtinput">
		<textarea name="message" id="message" placeholder="Enter a cool message..." tabindex="5" class="txtblock"></textarea>
	</section>

The first block area is wrapped in a section tag so we can float the layout side-by-side. The left column contains all these inputs: text, e-mail, URL, and telephone number. As you tab through on your phone the mobile keyboard display should adapt based on the input type. There are plenty of good reasons to support these features for mobile since everybody is working on-the-go these days.

The textarea element can also have a placeholder text defined on pageload. This is similar to a label which disappears once the user enters some text in the field. The attribute which isn’t carried over is autocomplete because textareas don’t usually fill in related content.

Sidebar Controls

I wanted to build this form so that it would respond appropriately to resizing window displays. When the window is full enough then both input columns are floating next to each other. But if the width is cut down slightly then the right-hand sidebar drops down below the main content.

Here’s my HTML for the sidebar area:

<section id="aside" class="clearfix">
	<section id="recipientcase">
	<h4>Recipient:</h4>
		<select id="recipient" name="recipient" tabindex="6" class="selmenu">
			<option value="staff>Site Staff</option>
			<option value="editor">Editor-in-Chief</option>
			<option value="technical">Tech Department</option>
			<option value="pr">Public Relations</option>
			<option value="support">General Support</option>
		</select>
	</section>
	
	<section id="prioritycase">
		<h4>Priority:</h4>
		<span class="radiobadge">
			<input type="radio" id="low" name="priority" value="low">
			<label for="low">Low</label>
		</span>
	
		<span class="radiobadge">
			<input type="radio" id="med" name="priority" value="med" checked="checked">
			<label for="med">Medium</label>
		</span>
	
		<span class="radiobadge">
			<input type="radio" id="high" name="priority" value="high">
			<label for="high">High</label>
		</span>
	</section>
</section>

This code actually isn’t anything too confusing. Just a simple option select menu and some radio buttons. Additionally, after these objects I placed a reset and submit button towards the end of the section.

<section id="buttons">
	<input type="reset" name="reset" id="resetbtn" class="resetbtn" value="Reset">
	<input type="submit" name="submit" id="submitbtn" class="submitbtn" tabindex="7" value="Submit this!">
	<br style="clear:both;">
</section>
</form>

This all looks well and good, so now let’s move into some CSS properties. There are so many customizations you can apply when working on form elements. Try not to bog yourself down with too much thinking and have fun!

Animated Box Shadows

You’ll notice as you tab through each of the main input elements that I’ve animated a colorful outer shadow. Google Chrome has an outline property which does something similar, but not quite as extravagant. This small part of the interface is alluring to first-time visitors.

/** the form elements **/
#hongkiat-form { box-sizing: border-box; }

#hongkiat-form .txtinput { 
  display: block;
  font-family: "Helvetica Neue", Arial, sans-serif;
  border-style: solid;
  border-width: 1px;
  border-color: #dedede;
  margin-bottom: 20px;
  font-size: 1.55em;
  padding: 11px 25px;
  padding-left: 55px;
  width: 90%;
  color: #777;
  
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) inset;
  -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) inset;
  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) inset; 
  
  transition: border 0.15s linear 0s, box-shadow 0.15s linear 0s, color 0.15s linear 0s;
  -webkit-transition: border 0.15s linear 0s, box-shadow 0.15s linear 0s, color 0.15s linear 0s;
  -moz-transition: border 0.15s linear 0s, box-shadow 0.15s linear 0s, color 0.15s linear 0s;
  -o-transition: border 0.15s linear 0s, box-shadow 0.15s linear 0s, color 0.15s linear 0s;
}

#hongkiat-form .txtinput:focus { 
  color: #333;
  border-color: rgba(41, 92, 161, 0.4);
  
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) inset, 0 0 8px rgba(41, 92, 161, 0.6);
  -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) inset, 0 0 8px rgba(41, 92, 161, 0.6);
  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) inset, 0 0 8px rgba(41, 92, 161, 0.6);
  outline: 0 none; 
}

In order to target each text element I’ve used the class .txtinput. Each of the transition properties work on border, box-shadow, and color. I’m using box-sizing: border-box; on the form container so padding doesn’t mess up our responsive design.

I had to copy over these same styles and edit them slightly for the textarea. I changed some of the padding and margins, and appended a unique background icon.

#hongkiat-form textarea {
  display: block;
  font-family: "Helvetica Neue", Arial, sans-serif;
  border-style: solid;
  border-width: 1px;
  border-color: #dedede;
  margin-bottom: 15px;
  font-size: 1.5em;
  padding: 11px 25px;
  padding-left: 55px;
  width: 90%;
  height: 180px;
  color: #777;
  
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) inset;
  -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) inset;
  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) inset; 
  
  transition: border 0.15s linear 0s, box-shadow 0.15s linear 0s, color 0.15s linear 0s;
  -webkit-transition: border 0.15s linear 0s, box-shadow 0.15s linear 0s, color 0.15s linear 0s;
  -moz-transition: border 0.15s linear 0s, box-shadow 0.15s linear 0s, color 0.15s linear 0s;
  -o-transition: border 0.15s linear 0s, box-shadow 0.15s linear 0s, color 0.15s linear 0s;
}
#hongkiat-form textarea:focus {
  color: #333;
  border-color: rgba(41, 92, 161, 0.4);

  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) inset, 0 0 8px rgba(40, 90, 160, 0.6);
  -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) inset, 0 0 8px rgba(40, 90, 160, 0.6);
  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) inset, 0 0 8px rgba(40, 90, 160, 0.6);
  outline: 0 none; 
}
#hongkiat-form textarea.txtblock {
	background: #fff url('https://assets.hongkiat.com/uploads/responsive-css3-form/speech.png') 5px 4px no-repeat;
}

Sidebar Inputs

The radio buttons and select menu items are styled much simpler. You can apply outer glow effects and similar drop shadows on these elements, but it doesn’t always look good. Alternatively designers will create custom user interfaces and attach these as background images. But this may require a jQuery workaround to keep the options displaying properly.

span.radiobadge {
  display: block;
  margin-bottom: 8px;
}

span.radiobadge label {
  font-size: 1.2em;
  padding-bottom: 4px;
}

select.selmenu {
  font-size: 17px;
  color: #676767;
  padding: 9px !important;
  border: 1px solid #aaa;
  width: 200px;
}

I haven’t done a whole lot to push these away from the main input elements. Plenty of extra padding is important so your users feel comfortable interacting with the form. When text is super tiny it can be a struggle just to fill out each part. Keep your font big, but not so big that it overwhelms the page.

Customized Buttons

The reset and submit buttons are designed in a class of their own. I have built a set of light gradients to match well with the blue highlights in our form fields.

Below is my CSS code for the submit button on standard and hover state.

#buttons #submitbtn {
  display: block;
  float: left;
  height: 3em;
  padding: 0 1em;
  border: 1px solid;
  outline: 0;
  font-weight: bold;
  font-size: 1.3em;
  color: #fff;
  text-shadow: 0px 1px 0px #222;
  white-space: nowrap;
  word-wrap: normal;
  vertical-align: middle;
  cursor: pointer;
  
  -moz-border-radius: 2px;
  -webkit-border-radius: 2px;
  border-radius: 2px;
  
  border-color: #5e890a #5e890a #000;
  
  -moz-box-shadow: inset 0 1px 0 rgba(256,256,256, .35);
  -ms-box-shadow: inset 0 1px 0 rgba(256,256,256, .35);
  -webkit-box-shadow: inset 0 1px 0 rgba(256,256,256, .35);
  box-shadow: inset 0 1px 0 rgba(256,256,256, .35);
  
  background-color: rgb(226,238,175);
  background-image: -moz-linear-gradient(top, rgb(226,238,175) 3%, rgb(188,216,77) 3%, rgb(144,176,38) 100%);
  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(3%,rgb(226,238,175)), color-stop(3%,rgb(188,216,77)), color-stop(100%,rgb(144,176,38))); 
  background-image: -webkit-linear-gradient(top, rgb(226,238,175) 3%,rgb(188,216,77) 3%,rgb(144,176,38) 100%);
  background-image: -o-linear-gradient(top, rgb(226,238,175) 3%,rgb(188,216,77) 3%,rgb(144,176,38) 100%);
  background-image: -ms-linear-gradient(top, rgb(226,238,175) 3%,rgb(188,216,77) 3%,rgb(144,176,38) 100%);
  background-image: linear-gradient(top, rgb(226,238,175) 3%,rgb(188,216,77) 3%,rgb(144,176,38) 100%); 
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#e2eeaf', endColorstr='#90b026',GradientType=0 );
}
#buttons #submitbtn:hover, #buttons #submitbtn:active {
  border-color: #7c9826 #7c9826 #000;
  color: #fff;
  
  -moz-box-shadow: inset 0 1px 0 rgba(256,256,256,0.4),0 1px 3px rgba(0,0,0,0.5);
  -ms-box-shadow: inset 0 1px 0 rgba(256,256,256,0.4),0 1px 3px rgba(0,0,0,0.5);
  -webkit-box-shadow: inset 0 1px 0 rgba(256,256,256,0.4),0 1px 3px rgba(0,0,0,0.5);
  box-shadow: inset 0 1px 0 rgba(256,256,256,0.4),0 1px 3px rgba(0,0,0,0.5);
  
  background: rgb(228,237,189);
  background: -moz-linear-gradient(top, rgb(228,237,189) 2%, rgb(207,219,120) 3%, rgb(149,175,54) 100%); 
  background: -webkit-gradient(linear, left top, left bottom, color-stop(2%,rgb(228,237,189)), color-stop(3%,rgb(207,219,120)), color-stop(100%,rgb(149,175,54))); 
  background: -webkit-linear-gradient(top, rgb(228,237,189) 2%,rgb(207,219,120) 3%,rgb(149,175,54) 100%); 
  background: -o-linear-gradient(top, rgb(228,237,189) 2%,rgb(207,219,120) 3%,rgb(149,175,54) 100%); background: -ms-linear-gradient(top, rgb(228,237,189) 2%,rgb(207,219,120) 3%,rgb(149,175,54) 100%); background: linear-gradient(top, rgb(228,237,189) 2%,rgb(207,219,120) 3%,rgb(149,175,54) 100%); 
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#e4edbd', endColorstr='#95af36',GradientType=0 );
}

It’s almost impossible to keep this type of selector clean! There are simply too many properties you need to list out and support for many older legacy browsers. Internet Explorer can even render these gradients with the proper filter. Notice aside from the background gradients I’ve also included a new border color, rounded corners, and a box shadow on hover.

The reset button looks similar but I’ve gone an entirely different route with the color scheme. Light gray tends to fall into the background in comparison to the bright green colors. Our reset button likely won’t be used very much, so it doesn’t need all the attention.

#buttons #resetbtn {
  display: block;
  float: left;
  color: #515151;
  text-shadow: -1px 1px 0px #fff;
  margin-right: 20px;
  height: 3em;
  padding: 0 1em;
  outline: 0;
  font-weight: bold;
  font-size: 1.3em;
  white-space: nowrap;
  word-wrap: normal;
  vertical-align: middle;
  cursor: pointer;
  
  -moz-border-radius: 2px;
  -webkit-border-radius: 2px;
  border-radius: 2px;
  
  background-color: #fff;
  background-image: -moz-linear-gradient(top, rgb(255,255,255) 2%, rgb(240,240,240) 2%, rgb(222,222,222) 100%);
  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(2%,rgb(255,255,255)), color-stop(2%,rgb(240,240,240)), color-stop(100%,rgb(222,222,222)));
  background-image: -webkit-linear-gradient(top, rgb(255,255,255) 2%,rgb(240,240,240) 2%,rgb(222,222,222) 100%);
  background-image: -o-linear-gradient(top, rgb(255,255,255) 2%,rgb(240,240,240) 2%,rgb(222,222,222) 100%);  background-image: -ms-linear-gradient(top, rgb(255,255,255) 2%,rgb(240,240,240) 2%,rgb(222,222,222) 100%);
  background-image: linear-gradient(top, rgb(255,255,255) 2%,rgb(240,240,240) 2%,rgb(222,222,222) 100%); 
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#dedede',GradientType=0 );
  
  border: 1px solid #969696;
  
  box-shadow: 0 1px 2px rgba(144, 144, 144, 0.4);
  -moz-box-shadow: 0 1px 2px rgba(144, 144, 144, 0.4);
  -webkit-box-shadow: 0 1px 2px rgba(144, 144, 144, 0.4);
  
  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
}
#buttons #resetbtn:hover {
  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);	
  color: #818181;
  
  background-color: #fff;
  background-image: -moz-linear-gradient(top, rgb(255,255,255) 2%, rgb(244,244,244) 2%, rgb(229,229,229) 100%);
  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(2%,rgb(255,255,255)), color-stop(2%,rgb(244,244,244)), color-stop(100%,rgb(229,229,229)));
  background-image: -webkit-linear-gradient(top, rgb(255,255,255) 2%,rgb(244,244,244) 2%,rgb(229,229,229) 100%);background-image: -o-linear-gradient(top, rgb(255,255,255) 2%,rgb(244,244,244) 2%,rgb(229,229,229) 100%); background-image: -ms-linear-gradient(top, rgb(255,255,255) 2%,rgb(244,244,244) 2%,rgb(229,229,229) 100%); background-image: linear-gradient(top, rgb(255,255,255) 2%,rgb(244,244,244) 2%,rgb(229,229,229) 100%); 
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#e5e5e5',GradientType=0 );
  
  border-color: #aeaeae;
  
  box-shadow: inset 0 1px 0 rgba(256,256,256,0.4),0 1px 3px rgba(0,0,0,0.5);
}

You could even drop the reset type and use this white/gray color scheme as your main submit button. I’ve used many of the same gradient styles and drop shadow effects, along with a text shadow for the inner label. It definitely provides a different feeling to the user experience.

Responsive Layout Changes

Moving into my other CSS file we can take a look at the simple responsive media queries I’ve setup. Any browser window above 800px will experience the full sidebar interface. As you get below this threshold the left column expands to 100% width and you see the sidebar elements drop down below.

@media screen and (max-width: 800px) {
	body {
		padding: 10px 15px;
	}
	#container {
		width: 100%;
	}
	#hongkiat-form #aligned {
		width: 100%;
		float: none;
		display: block;
	}
	#hongkiat-form #aside {
		width: 100%;
		display: block;
		float: none;
	}
	#hongkiat-form .txtinput, #hongkiat-form textarea {
		width: 85%;
	}
	#prioritycase {
		float: left;
		display: block;
	}
	#recipientcase {
		float: left;
		display: block;
		margin-right: 55px;
	}
}

As we get closer down in size I try to adapt each of the input forms. The width property can end up longer than the webpage itself and then we have input forms sticking out over the edge. This happens around 550px which is where I break the next query, along with both iPhone screen display resolutions for portrait and landscape.

/* smaller screen dropoff *******/
@media only screen and (max-width: 550px) {
 	#hongkiat-form .txtinput, #hongkiat-form textarea {
		width: 80%;
	}
}

/* iPhone Landscape ********/
@media only screen and (max-width: 480px) {
	body {
		padding: 10px 0px;
	}
	select.selmenu {
		width: 190px;
	}
}

/* iPhone portrait *******/
@media only screen and (max-width: 320px) {
	body {
		padding: 10px 0px;
	}
 	#hongkiat-form .txtinput, #hongkiat-form textarea {
		width: 70%;
	}
	#hongkiat-form #aligned {
		overflow: hidden;
	}
	select.selmenu {
		width: 160px;
	}
	#recipientcase {
		margin-right: 30px;
	}
}

Horizontal landscape mode still holds everything together very well. I’ve only made the dropdown select menu a bit thinner to make room for the radio buttons. In the portrait view, I’ve resized all the elements too much smaller widths. Now our code won’t break even in resized browser windows. But it’s nice to have support for iOS/Android smartphones as well.

Conclusion

I hope this tutorial has been informative in explaining just how much can be done on your webforms. The new CSS3 properties are powerful enough to build fully functioning animations with just a few lines of code. It’s truly an exciting time to be working in web development and following these trends.

If you have ideas or suggestions on the tutorial code feel free to share them with us via comment box below.

WebsiteFacebookTwitterInstagramPinterestLinkedInGoogle+YoutubeRedditDribbbleBehanceGithubCodePenWhatsappEmail