:first-letter is weird
:first-letter
's an ancient pseudo-element, which has excellent modern support. It can be used to add a drop-capital to paragraphs, like this. You're probably looking at it and thinking “this is another pseudo-element, right? Cool. I know how to use this. I've tinkered with :before
and :after
.”
Perhaps I’m projecting, because that’s exactly what I thought last week. I was wrong. Please, allow me to share what I’ve learned (I’ve created examples of all of these on this codepen).
It’s more of a selector, than an element
The :first-letter
selector finds the first character within an element, then applies certain styles to it. That even applies if you set a content
string on that element. Here's an example:
p:before {
content: "This is the before. ";
}
p:first-letter {
border: solid 1px red;
}
If the paragraph looks like this:
<p>I am a paragraph</p>
… then the red border will be around the “T” of “This is the before”, rather than the “I” of “I am a paragraph”. This will also happen if the content
is declared later in the code than the :before
element.
What if the content property is empty?
You can have a content declaration on a :before
which is an empty pair of quotes:
p:before {
content: "";
border: solid 10px green;
}
p:first-letter {
border: solid 1px navy;
}
As you might expect, the :first-letter
style will skip past it, onto the first character of the paragraph. However, as soon as you make the :before
pseudo-element display: block
, the first-letter fails to find a match. It doesn't match the :before
element or the first character of the paragraph.
This is because the first letter must occur on the first line of the containing paragraph. As soon as the :before
element becomes block
, it forces the following text onto a new line, so there's no longer a :first-letter
to find.
Can you stack elements?
What if you had a :first-letter
and an :after
element on the same paragraph, and you tried to stack them?
Their natural order would be :after
on top, as it appears second in the markup. But can you reverse this?
The answer is no — position relative
or absolute
has no effect on the :first-letter
element. And as a result, it doesn't matter what you set the z-index
of either element to (well, you could set the z-index
of the :after
to -1
, I suppose, but this would put it behind the whole paragraph, not just the :first-letter
)
Can you make it block
?
No. :first-letter
will take no other display
property other than inline
- not even inline-block
. This means that it will ignore any width
property applied to it.
Can you use outline
?
No. :first-letter
will not take an outline
style. This is nothing to do with it being display: inline
- inline elements can still have outline
applied to them. For whatever reason, outline
wasn't on the list of permitted properties (see below).
What does the specification say?
Perhaps I should have visited the spec before I did all my experiments and wrote this up. The W3C wiki lists all the properties which you can apply to :first-letter
:
- font properties
text-decoration
text-transform
letter-spacing
word-spacing
line-height
float
vertical-align
(only iffloat
isnone
)- margin properties
- padding properties
- border properties
- color property
- background properties
In addition, an article on CSS Tricks points out that :first-letter
can only apply to the first character of a block level element. So you can't use it to give an anchor tag a wee boost, for example (this might be possible, but you'd need to change the display
property of the anchor first).
When I was experimenting with :first-letter
, the properties which would work, and those which would not felt rather arbitrary. But the more I experimented the more it made sense: when you use :first-letter
, you aren't creating a new element in the DOM, you're just selecting whatever the character is at a particular position on the page. What's more, using the pseudo-class doesn't change its relationship with the rest of the paragraph. It remains firmly embedded inside that paragraph. The most you can do to change the flow of the paragraph is to float the :first-letter
to the right or left.