Font Dragr: A drag and drop font tester

After playing with the new file API draft spec available in Firefox 3.6 with my drag and drop upload article. I had another idea when I was playing with custom fonts, @font-face, in the browser. What if you could drag an drop a font file (otf, ttf, svg, woff) from your desktop into the browser and have text rendered on the fly using any available valid font.

In conjunction with Mozilla’s official announcement for the Web Open Font Format (WOFF) and continuing the wanky tradition of removing vowels from web app names, I introduce font dragr.

What is it?

Font dragr is an experimental web app that uses HTML5 & CSS3 to create a useful standalone web based application for testing custom fonts, once you visit it for the first time you don’t need to be online to use it after the initial visit. It allows you, in Firefox 3.6+, to drag and drop font files from your file system into the drop area. The browser will then create a data URL encoded copy to use in the page and render the content in the dropped font.

See it in action

Encoded files

I went about testing out a few theories on how I could dynamically add a dropped font to be used in the page. I saw this article on embedding custom fonts using a base64 encoded string. In the file API we have the getAsDataURL() method to return a file as a data url for using in a page, I used the same method in my drag drop upload demo to display the images.

Inserting into the stylesheet

The next hurdle was taking that data url and inserting it into the style sheet referenced on the page.

var styleSheet = document.styleSheets[0],
	fontFaceStyle = 
	"@font-face{font-family: CustomFont;src:url("+files[i].getAsDataURL()+");}";

styleSheet.insertRule(fontFaceStyle, 0);

In the above code we reference our style sheet using document.styleSheet[0]. We then build our style from the dropped file that we want to insert, notice the files[i].getAsDataURL() is where the magic happens and the current file is converted to a dataURL. We then use the insertRule method to prepend it to the style sheet.

Getting file information and applying the font

We also get the fileSize of the font and the fileName so we can populate the list item that we create on drop. With the file name I also do some crude validation and I also sanitise the file name in case there is any non alpha numeric characters, it will stop the font from being applied to the container if we have invalid characters.

acceptedFileExtensions = /^.*.(ttf|otf|svg|woff)$/i

droppedFileName = droppedFullFileName.replace(/..+$/,"");
droppedFileName = droppedFileName.replace(/W+/g, "-");

For the validation I have a regexp of accepted file extensions so it will only accept font types that work in Firefox. I remove the file extension from the fileName and then replace any non alphanumeric characters, W, with hyphens.

Once we have a semi-friendly name we use that to apply the font family style to the newly created list item and the content container. = droppedFileName;

International font friendly

Dragging in an international based font file will cause the text to render in a default sans serif font. To fix that I have made the main content area editable, you can type some text in your own language which should render in your international based font, this hasn’t been thoroughly tested. I would appreciate any feedback on using this demo with international fonts.

Work in progress

I am still very much actively refining and adding more features to this web app. If you have any of your own features/ideas please feel free to suggest/request any improvements or changes. Some I’m working on now.

  • Using localStorage object to store users dropped fonts and save edits to main content area. Main content edits are now stored in localStorage, hit size limit capacity with dropped fonts will look into webDB for font storage.
  • Better indicating to the user that the content can be edited
  • Making the drop area highlight on drag

I built this to fill a need I had, to quickly test custom fonts, and the idea has grown in to something much bigger and better than I thought it would be. I can see this as not only something cool to show off where HTML5 is heading but something genuinely useful.