The Heart of the Redesign: CSS Pseudo-elements

One of my favorite parts of my site’s recent redesign—and the page that I started the redesign with—is the new Portfolio page. This is where the whole “exposed markup” thing came from. Here’s what I’m talking about:

Adam Darowski : Portfolio

What was I trying to do?

I have a full-time gig as the User Experience Designer for BatchBlue. That affords me the ability to be a little creative with my portfoio—it isn’t my source of income. However, I do believe that all full-time designers should do a little freelance to stay fresh. So, I’d still like to show what I’m about.

The design traits I want to convey to prospective clients and readers are simplicity, elegance, cleanliness, and a sharp attention to detail. I also want to communicate that markup and style are at the heart of what I do. I do a lot of different things, but I’m always happiest with a text editor, a web browser, and a refresh button.

Given all this background, my goal was to work the underlying markup into the visual design.

How’d I do it?

Since the “exposed markup” is merely presentational, I wanted to keep it out of the “real” markup. Basically, when you “View Source”, I don’t want you to see <h1>&lt;h1&gt;Portfolio&lt;/h1&gt;<h1>. I wanted the nice, clean <h1>Portfolio<h1>. The best way I could come up with to pull this off was with the :before and :after CSS pseudo-elements.

Huh, pseudo-elements? Pseudo-elements are added to CSS selectors to give you a bit more selection control. The four pseudo-elements are :first-letter (allows you to style the first letter of the content contained within that tag), :first-line (allows you to style the first line), :before (allows you to add content before the tag), and :after (content after the tag).

The :before and :after pseudo-elements are great—except for one problem. You guessed it. IE. But not just IE6. IE7 still doesn’t support them. The additional content just doesn’t show up. For my portfolio, I decided that was a fine tradeoff. I’m really not targeting the type of users who would surf the web with IE (present company excluded, of course!). Besides, this approach actually well. If you use IE, you just don’t get the “exposed markup” tags.

Here’s how it looks in IE7:

Adam Darowski | Portfolio - in IE7

The markup

The pseudo-elements allow me to use a pretty standard definition list:

<dl id="active-projects">
  <dt><a href="">BatchBook</a></dt>
    <dd>Small Business <abbr title="customer relationship manager">CRM</abbr></dd>
    <dd>For <a href="">BatchBlue Software</a></dd>
    <dd>May 2007&ndash;Present</dd>
  <dt><a href=""></a></dt>
    <dd>Corporate Website &amp; Weblog</dd>
    <dd>For <a href="">BatchBlue Software</a></dd>
    <dd>May 2007&ndash;Present</dd>
  <dt><a href="">Tabigail</a></dt>
    <dd>A simple, gray, one-column, socially savvy WordPress theme</dd>
    <dd>For the WordPress community</dd>
    <dd>December 2008&ndash;Present</dd>
  <dt><a href="">BaseballTwit</a></dt>
    <dd>Blog posts and Twitter tweets about baseball stats and history</dd>
    <dd>For the sabermetric community</dd>
    <dd>December 2008&ndash;Present</dd>


First, we know we want the :before and :after content to always appear italicized and (my favorite color) gray. So, let’s use the global selector with the pseudo-elements. This way we don’t have to reapply the color and style over and over again.

*:before, *:after { color: #CECECE; font-style: italic; }

First, we’ll expose the opening and closing <dl> tags.

dl#active-projects:before { content: '<dl id="active-projects">'; }
dl#active-projects:after { content: '</dl> <!-- close #active-projects -->'; }

For the content property, you can either use a string (like I did), an image (via url(image.png)), or any of the following: open-quote, close-quote, no-open-quote, or no-close-quote.

Update: For some reason, this wasn’t rendering properly in Safari. The closing </dl> was appearing after the first <dt>. So, instead, I needed to wrap the <dl> in a <div> (giving the <div> the id of “active-projects” instead). This tricked Safari into putting the closing </dl> at the end of the <dl> where it belongs. If you know why Safari does this, please let me know!

Here’s the CSS for the <dt>:

dt { margin: 10px 0 10px 24px; font-size: 125%; }
dt a { font-weight: bold; }
dt:before { content: '<dt>'; font-size: 80%; }
dt:after { content: '</dt>'; font-size: 80%; }

In the first line, the margin gives a little space on the top and bottom, plus a proper indenting for our markup. Since the <dt> is used for the project name, I bumped the size up a bit. I also made the links bold to stand out a bit more. Then, of course, comes the :before and :after. In this case, I also dropped the font size for the tags a bit (to offset the increase in size of the links).

And now, the <dd>:

dd { text-indent: -38px; margin-bottom: 4px; padding-left: 56px; }
dd:before { content: '<dd>'; }
dd:after { content: '</dd>'; }

In addition to a little bit of a margin, I added a bunch of padding on the left and then used a negative text-indent. In the event that the <dd> goes to two lines, this will cause it to indent quite nicely.

And there you have it… pretty bits of markup used as a design element without muddying your “real” markup.


  1. On February 26th, 2009 at 7:29 am Mark said:


    It looks awesome! Very clean and professional in appearance – purposeful.
    I like the left sidebar list of social widgets and links to your other online presences / personas.
    In a way, these begin to resemble badges or campaign ribbons on a military uniform.
    The code is over my head – but it’s inclusion in the post certainly demonstrates the “blog as your resume” meme in action.
    Savvy, yet subtle. Glad things are going well at your new gig!


  2. On February 26th, 2009 at 11:45 am Adam Darowski said:

    Thanks Mark! Yes, things are gong great. That’s the main reason it took so long to find time to redesign. :)

    The military uniform comparison is one I haven’t heard. Perhaps more like Boy Scout merit badges!