Pseudo-elements in CSS: Creating Typographic Effects with ::first-letter

While the ::before and ::after pseudo-elements inject content, ::first-letter works with content that exists as part of the document source. With ::first-letter , we can create initial letter effects, such as drop caps, as you might see in a magazine or book layout.

This CSS snippet adds an initial capital letter to every <p> element in our document:

p::first-letter {

font-family: serif;

font-weight: bold;

font-size: 3em;

font-style: italic;

color: #3f51b5;


The result is shown below.

As you may have noticed from the image above, ::first-Letter will affect the Line-height of the first line if you’ve set a unitless Line-height for the element. In this case, each <p> element inherits a Line-height value of 1.5 from the <body> element. There are three ways to mitigate this:

  • Decrease the value of Line-height for the ::first-Letter pseudo-element. A value of .5 seems to work well most of the time, depending on the font.
  • Set a Line-height with units on the ::first-Letter pseudo-element.
  • Set a Line-height with units on either the <body> or the ::first-Letter

The first option preserves the vertical rhythm that comes with using a unitless Line-height . The second option limits the side effects of using a fixed Line-height just to those pseudo­elements. Option three, however, introduces a high likelihood that you’ll create a side effect that requires more CSS to undo.

In this case, let’s decrease the Line-height value for p::first-Letter to .5 (and rewrite our file properties to use the font shorthand):

p::first-letter {

font: normal 10rem / 1 ‘Alfa Slab One’, serif;

color: hsl(291, 64%, 30%);

display: inline-block;

padding-right: .25rem;


This change produces the result shown in the image below.

Notice here that we adjusted the bottom margin of each <p> element to compensate for the reduced Line-height of p::first-Letter .

Creating a drop capital requires a few more lines of CSS. Unlike an initial capital, the text adjacent to the drop capital letter wraps around it. This means that we need to add fLoat:Left; to our rule set:

p::first-letter {

float: left; /* Makes the text wrap around the drop cap */

font: normal 10rem / 1 ‘Alfa Slab One’, serif;

color: hsl(200, 18%, 46%);

margin-bottom: .4rem;

padding: 1rem 1.4rem 0 0;

text-shadow: 2px 2px 0px hsl(200, 100%, 10%);


Floating an element, or in this case a pseudo-element, causes the remaining text to flow around it, as illustrated below.

Be aware that ::first-Letter can be difficult to style with pixel-perfect accuracy across browsers, unless you use px or rem units for size, margin, and line height.

Sometimes the first letter of a text element is actually punctuation-such as in a news story that begins with a quote:

<p>&#8220;Lorem ipsum dolor sit amet, consectetur adipiscing elit.

→&#8221; Fusce odio leo, sollicitudin vel mattis eget, …</p>

In this case, the styles defined for ::first-Letter affect both the opening punctuation mark and the first letter, as shown below. All browsers handle this in the same way.

However, this isn’t necessarily how it works when the punctuation mark is generated by an element. Consider the following markup:

<p><q>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</q>

→ Fusce odio leo, sollicitudin vel mattis eget, iaculis sit …</p>

Current browsers typically render the <q> element with language-appropriate quotation marks before and after the enclosed text. Safari, Chrome, and Edge ignore the opening quotation mark. However, Firefox versions 90 and under apply ::first-letter styles to the opening quotation mark, not the first letter.

In Chrome-based browsers and Safari, neither the opening quotation mark for the <q> element nor the first letter of the paragraph are restyled. The image below shows how this looks in Chrome.

According to the CSS Pseudo-elements Module Level 4 specification[1] [2], punctuation that immediately precedes or succeeds the first letter or character should be included. However, the specification is unclear about whether this also applies to generated punctuation.11

In Firefox 90 and earlier, some punctuation characters cause Firefox to ignore a ::first-Letter rule altogether. These include, but are not limited to, the dollar sign ($), caret (a), back tick (‘) and tilde (~) characters. Firefox, to date, also doesn’t apply ::first-Letter styles to emoji.

This is true whether the first character is set using ::before and the content property, or included in the document source. There’s no fix for this. Avoid using these characters as the first character if you’re also using ::first-Letter .

The ::first-Letter pseudo-element doesn’t apply to elements such as <a> , <b> , or <code> . Nor does it apply to parent elements with a display property value of inline .

Source: Brown Tiffany B (2021), CSS , SitePoint; 3rd edition.

Leave a Reply

Your email address will not be published. Required fields are marked *