Facelifting the Facebook

This hack was patched within 12 hours of its discovery, so everything here exists simply for posterity. This did allow you to restyle your profile while it existed, but it was short-lived and isn’t allowed anymore. If you still think this was awesome, feel free to friend my Facebook Page. As of right now, there is no legitimate way to restyle your profile on Facebook. You are stuck with the default layout.

I’ve always hated MySpace, that awful interface, that network filled with scenesters and too many bands, prostitutes, and porn stars, that Inbox filled with spam messages from said bands, prostitutes, and porn stars. To me, MySpace was a social application gone wrong. That said, MySpace got something both wonderfully right and horribly wrong at the same time: it gave its users a rudimentary ability to style their profiles through bits of CSS.

Obviously, this power was grossly abused, as “designers” and general Internet users littered their profiles with a smattering of embedded video, audio, multi-megabyte GIFs, and colour palettes that would make Goethe descend from the heavens and smite them with a colour wheel. Truly ghetto design is ruling MySpace, keeping me as far away from it as possible. (I will admit that I do have a MySpace account solely to view links that friends send me. MySpace is definitely not a place I regularly visit.)

Facebook, on the other hand, has been able to avoid this problem; HTML has been disallowed in the larger text fields for over a year and a half: those attempting to use markup see the tags mysteriously stripped in preprocessing. That said, the design continuity, however bland it is, keeps text legible and all UI elements in the right places.

For some reason, I felt as if this protection from dismal “design” - which I’m grateful for - was also severely limiting to those of us who could design a Web page. I wanted to make my Facebook profile something more representative of me. (I actually considered e-mailing Mark Zuckerberg, Facebook’s creator, and asking if they’d host a CSS file for me. After deciding that my utopian vision was probably impractical, I set out to find a way to restyle my profile page last Monday when I should’ve been studying for a macroeconomics exam.)

I vaguely remembered a designer redesigning his MySpace page through some CSS trickery; a bit of Googling allowed me to rediscover Tim Benzinger and his wonderfully designed MySpace profile page (which is currently undergoing yet another redesign.) Unfortunately, the Benzinger hack was useless to me, as HTML was so severely limited on Facebook.

I spent a few more hours poking and prodding Facebook’s fields, software, and UI, eventually finding a workaround using the HTML DOM. When Hello, World! appeared in a JavaScript alert on my profile page, the hyaline hack was born.

The hyaline hack Part I: Facebook JavaScript insertion

I already knew that I couldn’t add style to common text areas, so I tried elsewhere, eventually being able to add an <em> tag to to the “Hometown” field. I then attempted to add a <div> with inline styles, only to find my work truncated by a character limit. This meant that I couldn’t attempt to do something like Benzinger had done; I only had 50 characters in the field. I was stuck. What if I used something like @import or <script>? Fifty characters proved too small for much of anything.

I wasn’t done: for those that remember the days of the old, pre-standards-compliant Web, people didn’t always use the type attribute with the <script> tag. I then attempted to write a script and reference it with just <script src=…, only to find that my URI was still too long for the 50-character limit.

Thankfully, many URL shortening services exist. By using TinyURL, I was able to barely work around the 50-character limit to insert a JavaScript into my Facebook profile page. It may not be a standards-compliant, but it’s a clever solution to a tricky problem. Thanks to this script insertion hack, I could use JavaScript to do most anything I wanted on my profile page.

The hyaline hack Part II: Modifying the DOM to force new CSS

Using JavaScript, a designer is then able to modify the HTML DOM to add (or delete) page content at will. Since I wanted to do more than just style certain elements, I needed to append a remote CSS file to the document <head> on the client side.

There are two ways to do this: in Internet Explorer, an array document.styleSheets is populated and a new stylesheet can be added to the document using the document.createStyleSheet method. As an example, if you have a CSS file at http://mysite.com/css.css, you can add your stylesheet to the document by using

document.createStyleSheet("http://mysite.com/css.css");

This will automatically append the stylesheet to the end of the styleSheets array; since we’d want the stylesheet rules to take priority in this case, this is ideal. document.createStyleSheet also contains an optional index argument if we want to add the stylesheet someplace else in the list. For example, to make the stylesheet first in the list, you’d call

document.createStyleSheet("http://mysite.com/css.css", 1);

In all other browsers, however, we’ll have to follow the DOM. There’s a three step process to inserting an element into a document: creation, attribute population, and insertion. The following sample code will create a <link> element, populate rel, type, and href, and then append the element to the bottom of the document <head>:

var reface_el = document.createElement(’link’);
reface_el.setAttribute(’rel’, ’stylesheet’);
reface_el.setAttribute(’type’, ‘text/css’);
reface_el.setAttribute(’href’, reface_style_uri);
document.getElementsByTagName(’head’)[0].appendChild(reface_el);

When you add the two methods together, you can make a neat function to insert a stylesheet into the DOM:

function reface_insertStylesheet(reface_style_uri) {
if(document.createStyleSheet) {
document.createStyleSheet(reface_style_uri);
}
else {
var reface_el = document.createElement(’link’);
reface_el.setAttribute(’rel’, ’stylesheet’);
reface_el.setAttribute(’type’, ‘text/css’);
reface_el.setAttribute(’href’, reface_style_uri);
document.getElementsByTagName(’head’)[0].appendChild(reface_el);
}
}

Once this function has been declared, we can then add your stylesheet to the Facebook profile DOM by calling reface_insertStylesheet(reface_style_uri), where reface_style_uri is the URI to your CSS file. Now that we can insert our own styles into the Facebook, we have to style the page using nothing but CSS.

The hyaline hack Part III: Restyling using CSS

Since we can’t edit our HTML structure, we’ve got to do things the real standards-based way and re-code the Facebook layout in CSS à la CSS Zen Garden. Thankfully, the Facebook’s XHTML markup is fairly semantic and largely free of inline style, making this part fairly simple.

Instead of taxing Facebook with design-time refreshes, download your profile page to your desktop and insert your stylesheet directly before </head>. (This is where the above script would insert the stylesheet anyway.) It’s best to leave Facebook’s own stylesheets enabled so you can see what parts of their styles will take precedence over yours.

While coding your stylesheet, however, there are a few pitfalls you’ll have to watch out for. Although it’s tempting to hide Facebook’s advertising with some cleverly placed display: none;s, as professionals, it’s ethical to leave them intact and just design around them. This also goes for the UI elements; it’s probably best to leave all the elements in roughly the same place so people can find their way around easily.

The textual “Facebook announcement” advertisements are inserted and styled by something that takes priority over your stylesheet; my guess is that JavaScript is restyling them upon page load. To force your formatting onto the text ads, you’ll need to use the !important declaration. This goes for the search box, too; you’ll find the important declaration, although dirty, a good friend as you restyle.

The hyaline hack Part IV: Implementing the hack

Since you don’t have access to Facebook’s servers, you’ll have to host your CSS, JavaScript, and all related support files on your own server (I set up a subdomain here to host my files. Free webhosts generally will not work.)

Once everything is uploaded, take the URI to your JavaScript and paste it into TinyURL to get a URL of suitable size. Copy the TinyURL to the clipboard and edit your Facebook profile, adding

<script src="yourtinyurl"></script>

to Home Town or Current Address (where, of course, yourtinyurl is your TinyURL.) (Note: You can restore the original text in that field by using a document.write in your JavaScript to conceal your script and keep whatever data you normally have there in place.)

Save your profile changes, and voila, you have restyled your Facebook profile.

Concerns, modifications, and add-ons

I’ve found one bug that I can’t really work around yet: if you use the “Home Town” field, facebook inserts a <wbr" (word break) into the middle of your script tag if you’re viewing the Facebook profile from outside the network. This means that to retain continuity, you’ll need to use a field such as Current Address, but doing so makes your redesign only available to those on your Facebook network.

You may also be afraid of breaking the Facebook’s Terms of Use; if you follow these directions and retain all UI elements in their original positions relative to their default layout, you do not break the Terms of Use with this hack, thus Facebook cannot reprimand you for this action (as of 25 March 2006, when this was written.)

Obviously, since this hack is JavaScript-based, the possibilities for modification are endless. My page, for example, restricts the restyling to Firefox, Safari, and Konqueror by detecting navigator.userAgent(). Technically, you could do everything from sIFR to script.aculo.us on your profile page; whatever you do is only limited by your knowledge of the HTML DOM and JavaScript. If you do simplify, modify, or otherwise improve this hack, please do e-mail me and tell me about your modifications; I’ll either link to them and/or roll them into my own official code. (Also, if you find this cool, you could always reward me with something from my del.icio.us wishlist, or, if you work in a great new media company, an internship for the summer… Enough of my panhandling. Go forth and facelift.)

Update (30 March 2006 13:53) - An anonymous source inside Facebook let me in on the fact that developers had originally considered allowing me to keep my style by hardcoding it into the Facebook’s software. An email to info@facebook.com from “Paul” has stated otherwise:

Paul from Facebook <comment -info-rt@facebook.com> to me
Hi,
I am sorry, but we cannot allow you to have a profile page that uses different formatting than the rest of the site. Thank you for not acting maliciously in exposing this vulnerability. In the future, just shoot us an email if you see any more problems. Thank you and enjoy the site!

No real thanks for even finding the vulnerability, just a form email from a site too big to bother when someone finds a nasty XSS exploit. If you’d like to style your profile as well, your best bet is to just e-mail info@facebook.com and tell them that you, too, want more than just that lame default style.

Update (26 March 2006 19:27) - Facebook has patched this hack. Already. Wow, that was fast.