How to Create an Upload Form using jQuery, CSS3, HTML5 and PHP


Topic: jQuery / CSS3
Difficulty: Advanced
Estimated Completion Time: 1 hour

In this tutorial we will code an Upload Form from Impressionist UI. We will code it using the Plupload API. Plupload allows you to upload files using HTML5 Gears, Silverlight, Flash, BrowserPlus or normal forms, providing some unique features such as upload progress, image resizing and chunked uploads. This way we are able to create a very powerful upload form compatible with all browsers. So let’s get started.

Step 1 – Files Structure

The file structure is very simple. First you need to download the “Plupload API” and the “jQuery UI Progressbar”. Then create all the necessary folders and add the files mentioned bellow.

  • css – Add here the .css files.
  • img – Add here the images.
  • js – Add here the scripts.
  • uploads – Here will be saved the uploaded files.
	-images files here
	-uploaded files goes here

Step 2 – HTML Markup

Create a <div> with the class “upload-form” and id “uploader”. Then we need to add the heading, the close button, the text paragraph, the select and upload buttons, the <div> were we will add the selected files, the progress bar and the close after upload checkbox.

<div class="upload-form" id="uploader">
	<!-- Form Heading -->
	<h1 class="replace-text">Upload Form</h1>
	<a href="#" class="close" title="Close Window"><img src="img/close-button.png" alt="Close"></a>

	<p>Laos, alongside many of its Southeast Asian neighbours, is well known for producing.</p>

	<!-- Select & Upload Button -->
		<a class="button" id="pickfiles" href="#">Select</a>
		<a class="button" id="uploadfiles" href="#">Upload</a>

	<!-- File List -->
	<div id="filelist" class="cb"></div>

	<!-- Progress Bar -->
	<div id="progressbar"></div>

	<!-- Close After Upload -->
	<div id="closeAfter">
		<span class="checkbox">
			<input type="checkbox" name="checkbox" id="checkbox">
			<label for="checkbox">Close window after upload</label>


Step 3 – Adding the Script Files

Next think that we will do is adding the JS scripts that we will use on our upload form. So we will start by adding the jQuery API, I’ve used the one hosted by Google CDN if you want you can download and host it on your own server. Next you need to add the “plupload.full.js” and the “jquery-progressbar.min.js” file. Add all this scripts to the <head> of you page.

	<meta charset="utf-8">

	<title>Upload Form Tutorial - by Valeriu Timbuc for Design Modo</title>

	<!-- Stylesheets -->
	<link rel="stylesheet" href="css/style.css" media="screen">

	<!-- Scripts -->
	<script src=""></script>
	<script src="js/plupload.full.js"></script>
	<script src="js/jquery-progressbar.min.js"></script>

Step 4 – Upload Form Configuration

In this step we will add the upload form functionality. Without this code it will not work. I’ve explained what does each piece of code with inline comments. Make sure you read them. If you have any question you can post on the comments. For more configuration setting you can read the Plupload Documentation.

	// Upload Form
	$(function() {
		// Settings ////////////////////////////////////////////////
		var uploader = new plupload.Uploader({
			runtimes : 'html5,flash,silverlight', // Set runtimes, here it will use HTML5, if not supported will use flash, etc.
			browse_button : 'pickfiles', // The id on the select files button
			multi_selection: false, // Allow to select one file each time
			container : 'uploader', // The id of the upload form container
			max_file_size : '100kb', // Maximum file size allowed
			url : 'upload.php', // The url to the upload.php file
			flash_swf_url : 'js/plupload.flash.swf', // The url to thye flash file
			silverlight_xap_url : 'js/plupload.silverlight.xap', // The url to the silverlight file
			filters : [ {title : &quot;Image files&quot;, extensions : &quot;jpg,gif,png&quot;} ] // Filter the files that will be showed on the select files window

		// Start Upload ////////////////////////////////////////////
		// When the button with the id &quot;#uploadfiles&quot; is clicked the upload will start
		$('#uploadfiles').click(function(e) {

		uploader.init(); // Initializes the Uploader instance and adds internal event listeners.

		// Selected Files //////////////////////////////////////////
		// When the user select a file it wiil append one div with the class &quot;addedFile&quot; and a unique id to the &quot;#filelist&quot; div.
		// This appended div will contain the file name and a remove button
		uploader.bind('FilesAdded', function(up, files) {
			$.each(files, function(i, file) {
				$('#filelist').append('&lt;div class=&quot;addedFile&quot; id=&quot;' + + '&quot;&gt;' + + '&lt;a href=&quot;#&quot; id=&quot;' + + '&quot; class=&quot;removeFile&quot;&gt;&lt;/a&gt;' + '&lt;/div&gt;');
			up.refresh(); // Reposition Flash/Silverlight

		// Error Alert /////////////////////////////////////////////
		// If an error occurs an alert window will popup with the error code and error message.
		// Ex: when a user adds a file with now allowed extension
		uploader.bind('Error', function(up, err) {
			alert(&quot;Error: &quot; + err.code + &quot;, Message: &quot; + err.message + (err.file ? &quot;, File: &quot; + : &quot;&quot;) + &quot;&quot;);
			up.refresh(); // Reposition Flash/Silverlight

		// Remove file button //////////////////////////////////////
		// On click remove the file from the queue
		$('a.removeFile').live('click', function(e) {

		// Progress bar ////////////////////////////////////////////
		// Add the progress bar when the upload starts
		// Append the tooltip with the current percentage
		uploader.bind('UploadProgress', function(up, file) {
			var progressBarValue =;
				value: progressBarValue
			$('#progressbar .ui-progressbar-value').html('&lt;span class=&quot;progressTooltip&quot;&gt;' + + '%&lt;/span&gt;');

		// Close window after upload ///////////////////////////////
		// If checkbox is checked when the upload is complete it will close the window
		uploader.bind('UploadComplete', function() {
			if ($('.upload-form #checkbox').attr('checked')) {

		// Close window ////////////////////////////////////////////
		// When the close button is clicked close the window
		$('.upload-form .close').on('click', function(e) {

	}); // end of the upload form configuration

Step 5 – Form Wrapper

Now we’ll start styling our form. First we’ll add some reset styles to the elements that we will be using. Then we’ll style the form container: add a background pattern and a css3 gradient on top; set the width to 200px (the total will be 250px because of the paddings); set the minimum height to 180px (the total will be 270px because of the paddings), we need to set the minimum because when we will add files to upload the box will need to be bigger; and add the rounded corners. We will also add a clear floats class to use it further.

/* Reset */
.upload-form div,
.upload-form span,
.upload-form input,
.upload-form a,
.upload-form h1,
.upload-form p {
	margin: 0;
	padding: 0;
	border: none;
	outline: none;

/* Form Container */
.upload-form {
	position: relative;
	z-index: 100;
	cursor: default;
	width: 200px;
	min-height: 180px;
	padding: 25px 25px 65px 25px;

	-webkit-border-radius: 3px;
	-moz-border-radius: 3px;
	border-radius: 3px;

	background: url(../img/upload-bg.png);
	background: -webkit-linear-gradient(top, rgba(255,255,255,0.1) 0%, rgba(0,0,0,0.1) 100%), url(../img/upload-bg.png);
	background: -moz-linear-gradient(top, rgba(255,255,255,0.1) 0%, rgba(0,0,0,0.1) 100%), url(../img/upload-bg.png);
	background: -o-linear-gradient(top, rgba(255,255,255,0.1) 0%, rgba(0,0,0,0.1) 100%), url(../img/upload-bg.png);
	background: -ms-linear-gradient(top, rgba(255,255,255,0.1) 0%, rgba(0,0,0,0.1) 100%), url(../img/upload-bg.png);
	background: linear-gradient(top, rgba(255,255,255,0.1) 0%, rgba(0,0,0,0.1) 100%), url(../img/upload-bg.png);

/* Clear Floats */
.upload-form .cb { clear: both; }

Step 6 – Heading & Close Button & Paragraph

To style the title we will set the font, the size, the color, etc. In this form I’ve added an image for the heading, so I’ve created a new class “replace-text” to replace the text with the image, basically we are hiding the text using the text-indent property and adding the image as a background. For the close button we will set the width and height and position it on the form container. To finish we will add some basic typography styles to the text paragraph.

/* Form Title */
.upload-form h1 {
	font-family: 'Trebuchet MS', sans-serif;
	font-weight: bold;
	text-transform: uppercase;
	font-size: 18px;
	color: #f6f6f6;
	text-shadow: 0px 1px 1px rgba(0,0,0, .65);
	padding-bottom: 2px;
	border-bottom: 1px solid #7a7b80;

/* Replace Title with Image */
.upload-form h1.replace-text {
	display: block;
	width: 100%;
	height: 17px;
	padding-bottom: 7px;
	text-indent: -9999px;
	background: url(../img/title.png) no-repeat left center;

/* Close Button */
.upload-form .close {
	position: absolute;
	display: block;
	width: 12px;
	height: 12px;
	top: 28px;
	right: 24px;

/* Paragraph */
.upload-form p {
	padding: 10px 0;
	font-family: sans-serif;
	font-size: 12px;
	color: #a4a5a8;

Step 7 – Select & Upload Buttons

Let’s style the buttons. We’ll start by adding the styles for both of them (css3 gradients, font, size and color, etc.). Then we will style the select button: set the width to 99px; make the left corners rounded; add a right border. For the upload button we will set the width to 100px and make the right corners rounded.

/* Select &amp;amp; Upload Buttons */
.upload-form .button {
	display: inline-block;
	height: 30px;
	margin: 15px 0;

	font-family: sans-serif;
	font-size: 14px;
	color: #777;

	text-decoration: none;
	text-transform: uppercase;
	text-align: center;
	line-height: 30px;

	background: #ffffff;
	background: -webkit-linear-gradient(top, #ffffff 0%, #f6f6f6 100%);
	background: -moz-linear-gradient(top, #ffffff 0%, #f6f6f6 100%);
	background: -o-linear-gradient(top, #ffffff 0%, #f6f6f6 100%);
	background: -ms-linear-gradient(top, #ffffff 0%, #f6f6f6 100%);
	background: linear-gradient(top, #ffffff 0%, #f6f6f6 100%);

.upload-form .button:hover {
	background: #f2f2f2;
	background: -webkit-linear-gradient(top, #f2f2f2 0%, #eaeaea 100%);
	background: -moz-linear-gradient(top, #f2f2f2 0%, #eaeaea 100%);
	background: -o-linear-gradient(top, #f2f2f2 0%, #eaeaea 100%);
	background: -ms-linear-gradient(top, #f2f2f2 0%, #eaeaea 100%);
	background: linear-gradient(top, #f2f2f2 0%, #eaeaea 100%);

.upload-form #pickfiles {
	width: 99px;
	float: left;
	border-right: 1px solid #999;

	-webkit-border-radius: 3px 0 0 3px;
	-moz-border-radius: 3px 0 0 3px;
	border-radius: 3px 0 0 3px;

.upload-form #uploadfiles {
	width: 100px;
	float: right;

	-webkit-border-radius: 0 3px 3px 0;
	-moz-border-radius: 0 3px 3px 0;
	border-radius: 0 3px 3px 0;

Step 8 – Selected Files

In this step we will style the selected files that were added to the upload queue. We will give some basics styles to it (background, typography, size, etc.). Then we need to style the “remove file from queue button”, the styles are also basic (width, height, background, etc.).

/* Added Files */
.upload-form .addedFile {
	position: relative;
	display: block;
	overflow: hidden;
	word-break: break-all;
	margin-bottom: 5px;
	padding: 0 0 0 25px;
	height: 30px;

	font-family: sans-serif;
	font-size: 12px;
	line-height: 30px;
	color: #646464;

	background: #f6f6f6 url(../img/file.png) no-repeat 5px center;

	-webkit-border-radius: 3px;
	-moz-border-radius: 3px;
	border-radius: 3px;

/* Remove File Button */
.upload-form a.removeFile {
	position: absolute;
	display: block;
	width: 10px;
	height: 10px;
	top: 10px;
	right: 10px;
	background: url(../img/remove-file.png);

Step 9 – Upload Progress Bar

Now it’s time to style our upload progress bar. As we are using the jQuery UI progress bar we need to use the classes generated by the UI in order to style it. We will start by giving a 4px height and 1px border radius. Then we will add a default background color and some shadows. After that we need to style the uploaded progress using a green css3 gradient. To finish we will style the tooltip that will show the uploaded percentage.

/* Progress Bar */
.upload-form .ui-progressbar,
.upload-form .ui-progressbar-value {
	position: relative;
	height: 4px;

	-webkit-border-radius: 1px;
	-moz-border-radius: 1px;
	border-radius: 1px;

.upload-form .ui-progressbar {
	cursor: pointer;
	margin: 15px 0 20px 0;
	background: #242424;

	-webkit-box-shadow: 0px 1px 0px rgba(255,255,255, .1);
	-moz-box-shadow: 0px 1px 0px rgba(255,255,255, .1);
	box-shadow: 0px 1px 0px rgba(255,255,255, .1);

.upload-form .ui-progressbar-value {
	background: #82d344;
	background: -webkit-linear-gradient(top, #82d344 0%, #51af34 100%);
	background: -moz-linear-gradient(top, #82d344 0%, #51af34 100%);
	background: -o-linear-gradient(top, #82d344 0%, #51af34 100%);
	background: -ms-linear-gradient(top, #82d344 0%, #51af34 100%);
	background: linear-gradient(top, #82d344 0%, #51af34 100%);

.upload-form .ui-progressbar-value span.progressTooltip {
	position: absolute;
	display: block;
	width: 36px;
	height: 14px;
	padding: 5px 0 4px 0;
	top: 10px;
	right: -18px;

	font-family: sans-serif;
	font-weight: bold;
	line-height: 14px;
	text-align: center;
	font-size: 12px;
	color: #646464;

	background: transparent url(../img/tooltip.png) no-repeat;

Step 10 – CheckBox

As we can’t style checkboxes, the easiest way that I’ve found to style theme using only CSS it’s by replacing the checkbox input with a span tag. This will work this way: first we will hide the checkbox input and style the span tag like a checkbox and then we will update the checkbox using jQuery. So when we will click on the span tag jQuery will update the checkbox input to selected, and when we will click again the span tag jQuery will remove the “checked” from the checkbox input.

As some users may have the JavaScript disabled we need to add a fallback. To do that we will add with jQuery a “js” class to the body tag. So if the JavaScript will be enabled on the page load it will add a “js” class to the body and if the JavaScript is disabled the class will not be added. So only the users with JavaScript enabled will have the custom styled checkbox.

/* Close Checkbox */
.upload-form #closeAfter {
	position: absolute;
	bottom: 25px;
	left: 25px;

.js .upload-form span.checkbox input[type=checkbox] {
	position: fixed;
	left: -99px;

.upload-form span.checkbox {
	position: relative;
	margin-top: 15px;
	float: left;

.js .upload-form span.checkbox {
	width: 21px;
	height: 21px;
	cursor: pointer;
	background: url(../img/checkbox.png) no-repeat 0 -21px;

.js .upload-form span.checked { background-position: 0 0; }

.upload-form span.checkbox label {
	position: absolute;
	top: 3px;
	left: 31px;
	font-family: sans-serif;
	font-weight: bold;
	font-size: 12px;
	color: #e4e4e4;
	white-space: nowrap;

All the styles that have the “js” class at the beginning will only be applied if JavaScript is enabled.

Step 11 – Checkbox Script

First we’ll add the “js” class to the body tag and make the checkbox “checked” by default on load. Then we will check if the checkbox is checked and if the result is false the checked class will be removed from the span and if the result is “true” the checked class will be added to the span tag. And also we will update the checked / unchecked state to the hidden checkbox.

// Check Box Styling
$(document).ready(function() {

	var checkbox = $('.upload-form span.checkbox');

	// Check if JavaScript is enabled

	// Make the checkbox checked on load
	checkbox.addClass('checked').children('input').attr('checked', true);

	// Click function
	checkbox.on('click', function() {

		if ($(this).children('input').attr('checked')) {
			$(this).children('input').attr('checked', false);

		else {
			$(this).children('input').attr('checked', true);



Step 12 – Upload.php

Open the upload.php file and comment this line $targetDir = ini_get("upload_tmp_dir") . DIRECTORY_SEPARATOR . "plupload"; and uncomment this one $targetDir = 'uploads';.


// Settings
//$targetDir = ini_get(&amp;quot;upload_tmp_dir&amp;quot;) . DIRECTORY_SEPARATOR . &amp;quot;plupload&amp;quot;;
$targetDir = 'uploads';


We finished this tutorial. Now you have a great upload form that you can use on your projects. If you have any questions post it on the comments section. Don’t forget to subscribe us for more tutorials and great articles.


Download Upload Form


  1. Daniel Simões Jun 13, 4:04 pm


    Is it possible to connect to a Database and update an ID?

    I want to upload image1, image2, image3… to a given ID.



  2. Valeriu Jun 13, 6:24 pm

    Hi Daniel,

    This upload uses the same plugin as wordpress (Plupload). If you have some php knowledge you can link and save and update ID’s to the database. For more information you can read the documentation or ask on the forums

    If you want to add custom data to an id edit this code:

    ‘ + + ‘‘ + ‘

    And attach to upload complete event the code to save it on the database.

    • Valeriu Jun 13, 6:33 pm

      Edit this code to change the ID:

      <div class=”addedFile” id=”custom_name_for_id’ + + ‘”>’ + + ‘<a href=”#” id=”custom_name_for_id’ + + ‘” class=”removeFile”></a>’ + ‘</div>

  3. JD Jun 15, 8:23 pm

    Excuse my noob comment, but…

    If two different visitors to my site upload an image with the same name will the first image be overwritten? I’m still uncertain how the server handles that.


    • Valeriu Jun 15, 11:14 pm


      No it will add an number at the end, you can also use a setting (unique_names : true) to generate unique files names.

  4. Sergio Jul 15, 10:20 pm

    Hi Valeriu,
    thank you very much for your tutorial, it is exactly what i was looking for, but i have a little problem:
    when i upload the file in the directory, nothing happens; there aren’t files in the folder.
    How can i solve this problem?

    Thank you

  5. Noel Aug 4, 3:39 pm

    Nice one!

    Is there an easy way of “echo’ing” back the uploaded file name / link when uploads are completed?
    Basicaly I woud like to see the “download” link when done with uploading.
    (I’m using it to upload small zip files)

    Thank you for this great peace of code!

  6. Someone Like You Sep 9, 1:17 am

    Thanks for the tutorial.
    How can i setup the max numbers of files ?
    I need to allow users to upload just 5 files.

  7. jcobhams Sep 18, 12:03 pm

    nice post but y don’t you just gather all file in to one zip for a quick download…some of us don’t want a tutorial but a quick fix to add to our apps and continue building….thanks nut nice post by the way

  8. Balachoudry Sep 28, 10:08 am

    This script support ‘s only images.I need to upload video files .. what are the changes need to be done. reply soon

  9. triasbrata Nov 1, 3:17 am

    it’s so nice upload design

  10. dave Nov 5, 10:05 am

    Can you create a source package with everything done and included i’m messing up somewhere and i don’t know where

  11. sankar s Nov 20, 12:54 pm

    Your code is very nice.
    How to show preview image.

  12. Christian Nov 23, 8:53 pm

    This is awesome! Is there a way for the user to add a title and description to each image that is uploaded so that it can be pulled at later time? For example, an artists page where they want to upload images to different categories, add titles and descriptions which would then be displayed onto the site?

    I know this might be long winded, but if you’ve worked on something similar to that I’d love to see it or know if this can be modified to suit those requirements.


  13. Melissa Nov 28, 8:47 am

    I changed the file size, but was wondering if there is an easy way to get notification via email if someone upoads to the site?

  14. Jacky Dec 1, 4:21 pm

    Is there a way to just include HTML4 and HTML5 support? I don’t want heavy upload for my site since Its main priority is not to accept uploads, I want to fall back to normal “preloader” if user doesn’t have HTML5.

    Pretty basic solution

  15. Olinto Dec 17, 9:44 am

    this is an excellent work my firends. I`m looking on the web for this kind of work. I want to know i ican do the same without HTML5

  16. Ian Dec 27, 7:09 am

    Love this script. Spent months looking for a customized ui for plupload and finally found this. Great work. One question however. I am requiring a callback function after the upload has completed. The default plupload functions have an init and pre init setting that I was previously using before I found this. I have attempted to add the init: setting into the general settings section but does not seem to work. Any help here would be greatly apreciated.


    • Ian Dec 27, 7:17 am

      Ignore my post above. I got it working :) I did not add a comma to the end of the previous line in the settings. My Bad :)

  17. David Mar 9, 2:18 am

    If I use the latest version of PlupLoad (1.5.6) then this form doesn’t work, however if I use the one included in the download from designmodo it works fine. Any ideas?

  18. Akin Mar 9, 1:11 pm

    and would you be so nice to share your solution how to add video?

  19. deen Jul 31, 1:44 pm

    it have delete function?

  20. Maitreya Vyas Aug 10, 7:33 pm

    Is there any way to integrate this with Dropbox or Skydrive?

  21. Molly Jun 20, 7:52 am

    I changed the max file size allowed, but it seems to be limited.
    What is the largest file size this can be set to upload successfully and why?

    Thanks for the tutorial, I had a lot of fun with this!

  22. vegihat Dec 6, 12:45 am

    Nice post and clear code!

    which is the id of the file object so then i can read it?

    for example if we had

    then to read the first file i would do
    var finput = document.getElementById(“example”);
    var f = finput.files[0];

  23. DJ Jul 15, 1:42 am

    I would like to move the Upload button outside the box, change it to Submit, and use it with form data, i.e. name, address, phone numbers, etc. and submit the form (with or without uploads)? Is this possible with this code?


  24. Kumar Feb 19, 3:21 am

    I am forcing raise the error on the server size and setting the properly error object. But, not able to see them on the upload form.

    Is there way that i can access the server side errors as they are being returned as Json data.

    help please!!!!

  25. Edward May 11, 11:06 am

    Will this script run on a WildFly (Jboss) server ?

Leave a Reply

* Minimum length: 20 characters