Styling text with pseudo-elements

Learn about two CSS pseudo-elements, :first-letter and :first-line, which enable you to create styles that apply to the first letter or first line of a text element such as a paragraph.

Most Web builders are familiar with using CSS pseudo-class selectors to style the different states of hyperlinks in order to achieve rollover effects. However, you may not be aware of another "pseudo" selector that you can use to create text effects, such as initial caps.

The selector constructs I'm referring to are the :first-letter and :first-line pseudo-elements, and they enable you to create styles that apply to the first letter or first line of a text element such as a paragraph. They're called pseudo-elements because they work as if there was an extra markup tag (such as a <span> tag) defining the first letter or first line as a separate element that can then receive its own styling.

Creating an initial letter effect

A classic typographic effect that is often used to add emphasis to the beginning of a text passage is to accentuate the first letter of the first word with some distinctive formatting. Ancient manuscripts were famous for their elaborate initial letters at the beginning of each chapter or verse, but we don't see that treatment much anymore. The modern initial letter effect is usually more sedate, with an initial letter that is just a little bigger and bolder than the normal text that follows. We can create this effect easily with the :first-letter pseudo-element.

Suppose you want to accentuate the beginning of each paragraph of text as shown in Figure A. You could start with the following XHTML markup. (The text within the <p> tags has been abbreviated to make the example code easier to read.)

<body>
<p>Or bends with the remover ... nor no man ever loved.</p>
<p>Which alters ... no man ever loved.</p>
<p>Love's not time's fool, ... it is an ever fixed mark.</p>
</body>

And then you could apply the following CSS styles to achieve the effect:

p {
    font-family: Verdana, Arial, Helvetica, sans-serif;
    font-size: 12px;
    line-height: 16px;
    color: #000000;
}
p:first-letter {
    font-size: 30px;
    font-weight: bold;
    color: #FF0000;
}

There's nothing in the markup that separates the first letter from the rest of the text, but you can still apply distinctive styling to the first letter of each paragraph by defining that formatting in the p:first-letter style. The rules in the p:first-letter style override the corresponding rules in the p style, but only for the first letter in each paragraph.

Combining and controlling the effects

Now, suppose you want to combine the initial letter effect with one that accents the first line of text as well—but you only want the effect to appear on the first paragraph, not on the paragraphs that follow.

The combined effect shown in Figure B may look tricky, but it's fairly easy to accomplish. The :first-line pseudo-element enables you to format the first line of a paragraph just as the :first-letter pseudo-element does for the initial letter. The :first-line pseudo-element works better than <span> tags for selecting the first line of text because the selection adapts automatically to changes in line lengths as the browser window is resized. Combining the :first-letter and :first-line pseudo-elements with a class (or ID) applied to a specific paragraph tag in the markup enables you to restrict the effect to that paragraph.

Here's the XHTML markup for Figure B (with the text abbreviated as before):

<body>
<p class="firstgraf">Or bends with the remover to remove .... nor no man ever
 loved.</p>
<p>Which alters ... no man ever loved.</p>
<p>Love's not time's fool, ... it is an ever fixed mark.</p>
</body>

And here are the CSS styles that create the effect:

p {
    font-family: Verdana, Arial, Helvetica, sans-serif;
    font-size: 12px;
    line-height: 16px;
    color: #000000;
}
p.firstgraf:first-letter {
    font-size: 30px;
    font-weight: bold;
    color: #FF0000;
}
p.firstgraf:first-line {
    font-size:18px;
    font-weight:bold;
    line-height:18px;
}

Caveats and notes and browser compatibility (oh my)

You need to keep a few things in mind as you work with the :first-letter and :first-line pseudo-elements. First, the pseudo-element must be the last construct in the selector portion of your CSS code. For example, div#main p.firstgraf:first-line is a valid use of the pseudo-element, but p:first-line a:link is not.

Secondly, when you create an initial letter effect with :first-letter, the initial letter is still part of the main text block, so you can't really position it independent of the rest of the text. As a result, this technique isn't a good way to create drop cap effects where a large initial letter should extend below the text baseline and the following text lines should flow around it. Letter spacing is also hard to control with the :first-letter pseudo-element, so it doesn't work well for large, heavily undercut letters (such as T and W) followed by small text.

Finally, you need to consider browser support for the pseudo-elements. Generally, browser support for these selectors is reasonably good among the current versions of the major browsers. However, the same can't be said for older versions of those same browsers.

Fortunately, selectors containing the :first-letter and :first-line pseudo-elements are generally ignored by the older browsers, which means that the text appears normally, without the initial letter (or line) effect. Since these effects are usually optional visual enhancements, you can often accept the loss of the effect in the deficient browsers without resorting to hacks or alternate formatting to compensate for those deficiencies.