Matthew Buchanan portrait by Photobooth SF

About the author

I’m a designer and practitioner of fine typography in Auckland, New Zealand. I co-founded a design and development studio, Cactuslab, in 2001, and a social network for film fans, Letterboxd, in 2011. I design themes for Tumblr, speak occasionally about web techniques and typography, and think up reasons to visit New York City.

Matthew Buchanan

Posted on Friday, 6 June 2008

Theming Tumblr

Over the past couple of weeks I created a custom theme for Tumblr, which you can see here if you’re reading this post via the Tumblr Dashboard or RSS.

The process was largely fun and easy. After many CMS integrations with multiple user-facing templates, it’s refreshing to work with Tumblr’s single-page approach. The Tumblr engine derives every page on a user’s tumblelog from a single HTML and CSS template, vastly reducing not only the amount of work required to generate a custom theme, but also the quantity of repeated code (in particular compared to a default WordPress installation).

Creating a custom theme

The first step in the implementation of a custom theme is to produce an HTML page, plus CSS and images, to represent the design. To this we add custom tags to help Tumblr identify the component parts of the page, including variations in markup for each post type (more on those below).

Next, copy the HTML (containing embedded CSS if you wish) directly into the “Custom HTML” field in Tumblr’s Customize section, now accessed from the Dashboard. Use the Preview button to verify that your custom tags are correctly configured.

As part of the process, I was expecting to upload image and CSS files to Tumblr, but at present the service does not provide hosting for files that are part of a custom theme (other than for official/public themes). Instead, I created a subdomain of my site to use as storage for both image and CSS files.

Working with custom tags

Tumblr’s tagging language (and supporting documentation) is excellent, although I did strike a couple of issues. One of the more annoying is the incomplete nature of the preview page used to test a theme in progress:

  • example posts aren’t tagged
  • video and audio posts, pagination, and followers lists aren’t displayed
  • there’s no lists, headings or pre-formatted code in content blocks
  • optional content for permalink, tagged, and day pages is not included

While not insurmountable, it would be useful for this content to reflect more of the possible output from a Tumblr page in order to facilitate better testing (perhaps with multiple preview pages). My only option was to make my theme live during testing and manually navigate to various pages to ensure all styles worked as expected. Update: I now use a separate “sandbox” account for testing all my custom theme work.

Tumblr custom tags come in two varieties: variables, for outputting dynamic data, and blocks, for looping through data sets or conditionally outputting dynamic data. This approach covers most situations, however there’s no notion of “else” or “not”, so it’s not possible to output content when the result of a conditional operator evaluates to false, as would have been useful on a couple of occasions. Update: If-style block tags now support IfNot as well.

Tumblr’s 404 (error) pages use a post of type “text” to output error messages. The permalink on text posts in my custom theme is styled with a clock image and uses the {TimeAgo​} custom tag to output its link text. On the 404 page, there is no permalink, however without being able to identify if the current page is (or is not) an error page, I have no way of hiding the icon accordingly.

One peculiarity I encountered involves the {block:​PermalinkPage} custom tag, which must appear inside a {block:​Posts} block. This requirement isn’t mentioned in the documentation and is not the case for similar tags {block:​DayPage} or {block:​TagPage}.

Tagging and filtering posts

While we’ve been able to categorise Tumblr posts using tags for some time, access to those tags from a custom template was, until recently, severely restricted. This all changed when the fine Tumblr folks announced support for filtering by post tags. We can now display a list of tags for each post, and display a list of all posts with a given tag, using a URL like

In fact, tag support is now so good I’m craving a better way to manage tags. I’d like to see a tag editor in the Dashboard that displays a list of my tags with a post count for each. Support for editing (and merging) of tags would make it easy to fix inconsistent application of tags across all posts.

On the topic of tags, I’m interested in the decision to use the underscore character to represent white space in a tag, in comparison to Tumblr’s post summary URLs which use the more favoured dash.

Lastly, like Danny Garcia, I’d like to be able to filter posts by type, for example: to display all audio posts, with an optional /chrono suffix to display the list in chronological order (as you can for /tagged pages), and support for filtering reblogs as well. Of course it’s possible to use tags to accomplish this, but that defeats the purpose when post-type and reblog data is stored for each post already. It’s curious that the above URL goes not to a 404 page, but redirects to the Dashboard to show all requested post types there instead. Perhaps an indication this feature is in the works?

This is getting long

Three final suggestions: I’d like to be able to view “draft” posts more easily in the Dashboard, ie. those posts that are set to be visible only by me. As it stands, these entries are saved in the main timeline and there is presently no filter option to display based on privacy status. Update: Tumblr now supports queueing (for staggered, automated posting) and draft post options/management.

Search: sure, there are AJAX solutions, but they don’t feel very nicely integrated. Support for search that returned a page of results using the existing template layout would be preferable. Update: the lovely Tumblr folk have implemented proper search!

The audio player: it’s virtually the only part of the interface I don’t have control over when creating a custom theme. Perhaps allowing a SWF “interface” file to be loaded into the player, with specified names applied to each of the mandatory movie clip elements, might be an option. At the very least give the interface a bit of love. And yes, it could do with a volume control. Update: SWF LOL.