Lettering.js was built to solve a problem. As web typography improves, web designers want the same level of control print designers have.

Just as we’ve moved beyond Helvetica and Times New Roman, we’ve begun to think about web type in finer detail than <h1> or <span> tags currently (semantically) allow. For example, when Dave Rupert and I prepared to markup the 3 sites for the Lost World’s Fairs project, we saw elements in each design that would require an excessive number of <span> tags to target words, even letters, at a time.

El Dorado
The Moon

Ideally, CSS selector pseudo classes or elements would work, but even with options like :nth-child and ::first-letter we wouldn’t be able to target all that we needed.  As eager as we were to dive into building these beautifully designed pages, we couldn’t help but realize two things:

  1. We needed more control over letters, words, and lines than CSS currently provided for.
  2. The markup was going to be extremely difficult to manage because wrapping individual letters in <span> tags would get messy quick.

An hour later Dave came back with the best solution we could think of: a simple jQuery plugin that injected <span> tags around letters, words, or lines within any declared element. Lettering.js let us build out & revise the pages, saving heaps of code as well as grunt work. It was such a lifesaver that we decided to share it with the web community, launching letteringjs.com late fall 2010.


Lettering.js was well-received, though there are a few valid criticisms that I’d like to briefly address:

If you buy good fonts, they don’t need to be kerned.

That may be, but some fonts do, and the thinking behind Lettering.js goes beyond kerning into overall control. What if web designers want to use italics, font-size, or even change font-family within an element?

Lettering.js isn’t the only way.

True, and it isn’t the ultimate solution either. Let’s consider our options from most problematic to least:

  1. Embed an image
  2. Use CSS image replacement
  3. Wrap letters or words in <span> tags
  4. Use JS to inject <span> tags after the markup as we have with Lettering.js

Even though the <span> tags aren’t in the markup, there’s still bloat.

This is true. While Lettering.js keeps the source HTML clean, it doesn’t do the DOM any favors and inserts quite a bit of code.

Load times are increased. Javascript libraries are loaded just to target a few words or letters.

Again, consider the alternatives.  An image could easily outweigh javascript code.  On the other hand, yes, it’d be ideal to do this independently from JS.

Can we replace Lettering.js with CSS?

I hope so. Lettering.js is a solution, but perhaps it’s not the ultimate solution. As I mentioned earlier, CSS Selectors come close. What if the CSS spec was adapted to fill in the gaps? After scouring the internet, here’s a brief timeline recounting what’s already been discussed.


The W3C proposed Cascading Style Sheets, level 1 (CSS1) featuring the ::first-letter and ::first-line pseudo selectors.


Anne Van Kesteren explored the idea of expanding selectors to cover ::nth-line(n) and ::nth-letter(n).


Safari 1.3 was released as the first browser to fully support both the ::first-letter and ::first-line pseudo selectors. It’s worth mentioning that prior to this, IE5.5+ (July 2000 ) and Firefox 1 (November 9, 2004 )  had partial/buggy support for these selectors.


An extensive (50+ message) CSSWG thread on Proposed ::last-line and ::last-letter selectors was started by Andrés Delfino. The feasibility was discussed at length, and rejected due to narrow user base and high cost / complexity.

At the time, this thread had trouble coming up with good use cases. With the expansion of pseudo selectors & available web fonts, good use cases are now everywhere. The discussion focused heavily on ::last-line and ::last-letter which may not be particularly useful.


As a necessity, Dave Rupert built Lettering.js as a workaround.  Version 0.6.1 has been downloaded 1500 times, with 550 watchers on Github, indicating that alongside the growth of web fonts, the ‘narrow user base’ is widening rapidly.


From CSS1, we’ve been able to use pseudo-elements to target ::first-letter.  What if you extended that idea to targeting letters, or even words, within an element similar to the CSS3 ::nth-child(n) selector, resulting in something like this:

  • h1:nth-letter(4); or h1:nth-char(4); targeting the 4th letter within an <h1> tag.
  • h1:nth-word(3);

    targeting the third word within an <h1> tag.

I think this would be the ideal solution from a web designer’s perspective. No javascript would be required, and 100% of the styling would be handled right where it should be- in the CSS. On the other hand, I have no idea what goes into implementing these additions for a browser, which is why the idea has been proposed as a blog post with comments. Please, feel free to share your own thoughts about how we can gain more typographic control on the web.