Thursday, September 23rd, 2010

How Gmail’s Drag and Drop from the Desktop Works

Category: Google

The CSS Ninja details how Gmail’s drag and drop from the desktop works; when you drag a file from the desktop into Gmail the file will automatically start uploading.

The CSS Ninja recreated the code in a demo (source code [zip]).

The code works in Firefox and Chrome. On Firefox the File API is used (detailed in another blog post) while on Chrome a different API is used.

How does Chrome work?

Using a bit of CSS trickery we can create the illusion of having File API support and still allow users to drag and drop files from the desktop into Gmail. I accomplish this by having the drop zone, which becomes visible on a dragenter event, contain an invisible file input with a 100% width and height of the drop zone area. The file input also has the attribute multiple on it allowing a user to drop multiple files.

  1. <div id="drop">
  2. <h1>Drop files here</h1>
  3. To add them as attachments
  5. <input id="filesUpload" type="file" /></div>

The drop zone is hidden by default until a dragenter event happens on the BODY tag:

  1. #drop {
  2. position: relative;
  3. }
  4. #drop input {
  5. position: absolute;
  6. width: 100%;
  7. height: 100%;
  8. top: 0;
  9. left: 0;
  10. opacity: 0;
  11. }

When the drop input is activated a change event is fired and the files can be enumerated:


  1. dropArea.addEventListener("change", TCNDDU.handleDrop, false);
  3. TCNDDU.handleDrop = function (evt) {
  4. var files =;
  5. = "none";
  6. for(var i = 0, len = files.length; i &lt; len; i++) {
  7. // iterate over file(s) and process them for uploading
  8. }
  9. };
The actual uploading is handled by XHR2:

Using XHR2 and the upload attribute to attach progress events so we can do a real progress bar that indicates to the user how much the file has uploaded.

Posted by Brad Neuberg at 6:00 am

2.7 rating from 3 votes


Comments feed TrackBack URI

that article is dating of before Chrome 5 and Safari 5. Now native drop is supported on those, no more need for the invisible INPUT trick

from the implementation I made, I discoverd limits to the use of FileReader for big files ( > 10Mb) :
– huge CPU bloat on the browser
– huge memory consumption on the server

Gmail limits the size of the attachment so that was not a probleme for them

your today’s best choice would be to use the FormData that comes with XHR2, see this mozilla post :

ironically Chrome and Safari support it since version 5, but Firefox supports it only in Firefox 4
so I guess the GMail team will soon update his code

Comment by jpvincent — September 23, 2010

wasn’t this article already posted last month?

Comment by naterkane — September 23, 2010

The article from last month was focused on a different aspect of Gmail.

Comment by Brad Neuberg — September 23, 2010

@jpvincent – Handling large files is in the spec through the use of the url attribute to load it from the file system rather than into memory. There is also the slice method to split up large files into usable chunks. Firefox 4 has support for the url attribute although there is currently a bug when drag and dropping a file. However, looking at the status of that bug looks like they’ve renamed url to possibly internalUrl or mozFullPathInternal based on this commit will have to confirm that.

@naterkane – The other article was to do with dragging out of the browser, this one dragging in.

@Brad – Thanks for the link love!

Comment by Ahrjay — September 23, 2010

@Ahrjay : so to avoid memory bloats, you suggest to upload a file by splitting it with File.slice() on the browser and sending it with multiple XHRs ?
about the url attribute, I havent tested it yet but isnt it the same as using xhr.send(file); ?
if so, a say 50Mb pictures freezes the browser during several seconds while taking memory

do you think saying FormData seems to be the perfect way to handle uploads ?

Comment by jpvincent — September 24, 2010

@jpvincent – If you’re doing drag and drop uploading, splitting a large file and uploading it in smaller parts would be optimal as you can have more than one xhr send at the same time. If it’s a form with a file submit FormData interface would be a better solution although it’s only in FF4 at the moment.

I’ve also got an answer for the .url deprecation in FF4 it’s been moved to window.createBlobURL().

Comment by Ahrjay — September 24, 2010

Leave a comment

You must be logged in to post a comment.