Anyone who has been using a computer for any length of time is familiar, perhaps to the point of no longer even noticing, with drag and drop as a means of organising files and data.

Until the release of HTML5, implementation of similar functions within the web browser environment involved weighty jQuery plug-ins. This wasn’t an easy or pleasant option and needed a certain amount of coding knowledge to really turn the idea into a workable principle. Sure, certain content within all webpages is draggable by default. Try it on an image or and you’ll see a ghost image of the element being dragged around the page.

This will drop back into place when the mouse button is released but this is not what we are trying to recreate here. If you want the ability to be able to actually do something more functional with a draggable element, you can call on the HTML5 drag and drop API to handle it.

In this tutorial, we’ll look at some of the ways you can use HTML5’s drag-and-drop functionality. We look at how to order and manipulate images on a webpage and drag into their own specified areas.

Create an image grid

Firstly we need to create an image grid. It’s entirely up to you how many images you want to include in your grid. Our tutorial grid has 20 images; five rows of four. Give each frame class a width of 25% and auto centre the containing grid. Style everything else to taste.

The Image Library

Once you have put together your grid, complete with any other styling you wish to add, we are left with a nice looking set of images. Nice, but pretty static. Now the intention is to be able to rearrange the order of our image grid using some HTML5 magic.

Define draggable elements

Any element can be made draggable by simply setting the draggable=”true” attribute to it. This must be added to every image that we wish to make draggable. There will be no visible results just yet. The ghost image when we try to drag the element is normal and browser specific.

Understanding the events

The drag-and-drop process involves a number of events firing in a certain order. The three main events are dragStart, dragOver and drop. These three direct the taking, moving and delivering of the draggable element and can be supplemented by dragEnter, dragLeave and dragEnd, to define behaviours during and after the drag and drop.

dragStart function

Open up a script tag and begin placing the following inside it. We begin by declaring our source element, which is the element that will be dragged and moved. The element in question will change depending on which of our images is being moved at any given point in the process.

dataTransfer function

The dataTransfer property dictates what action the dragging element can perform. It can be set to none, copy, copyLink, copyMove, link, linkMove or move, and move is what we want to use. The setData property controls what data from the element is carried. ‘Text’ should be set, rather than ‘html’, as an IE doesn’t work with ‘html’.

dragOver function

Below the dragStart, we can add our initial dragOver function. We will add particular dragOver effects later in the process, but for now it’s good practice to use the property to prevent the browser from following its default behaviours, which usually results in an unwanted redirect.

drop function

Now we can put in place the penultimate step in the first draft of our demo, the drop function. First, another default browser preventative needs to be planted. This particularly helps with Firefox, which links to the image by default. Then we swap the source data with the target data, using the dataTransfer’s getData.

Set event listeners

Adding event listeners for our three functions, targeted to the frame classes, will get the whole thing up and running. Now you can drag each thumbnail image and place it in the space occupied by another. They will then swap places.

CSS additions

Now we can start ironing out some user experience details in the CSS. Firstly, we need to ensure that users see a cursor change when they hover over our draggable elements. By placing ‘cursor:move;’ into the containing div, users will see the crosshair to indicate a moveable element. The ‘[draggable]’ elements should also be unselectable.

Adding dragOver effects

The dragOver function can add a class to whichever element the source image hovers over. The class can then be given a style in the CSS. In this case, a reduced opacity for the target. Don’t forget to add the listener to the group. For the moment, elements stay this way once hovered over.

dragLeave function

By adding a dragLeave function, we can ensure that any classes applied during the dragEnter are cancelled out after the hovering element has left. Without restoring the original opacity, you will leave a trail of faded images in your draggable element’s wake, although there may be a time when this effect is actually more desirable!

Add dragStart effects

We won’t just leave the novel effects with a simple hover. You can choose when and where you add a variety of effects, starting when an element is ‘picked up’. In this case, we’ll add a CSS3 animation that will cause the source image to ‘wobble’ once it is dragged. But we’ll need to end the case, as well.

dragEnd event

We’ll use the dragEnd function to turn off the wobble effect once a single drag-and-drop move has been completed, otherwise you could eventually have a gallery of shaking images. Once again, remember to add the Event Listener to the end of the script.

Custom drag image

It’s possible to replace the default ‘ghost’ image that appears when dragging an element with a custom image or icon of your own. All you need to do is add the code inside the handleDragStart function, below the setData declaration. The x and y co-ordinates set distance from the cursor.

Applications

At first glance this function may seem fun but ultimately gimmicky, however drag and drop has been an integral part of the web experience for longer than you may realise. HTML5 drag and drop is admittedly still a little rough around the edges, and very browser inconsistent, but still offers a variety of plug-in-free solutions.