Notice: The WebPlatform project, supported by various stewards between 2012 and 2015, has been discontinued. This site is now available on github.

pseudo-elements

Pseudo-elements create abstractions about the document tree beyond those specified by the document language. For instance, document languages do not offer mechanisms to access the first letter or first line of an element’s content. Pseudo-elements allow authors to refer to this otherwise inaccessible information. Pseudo-elements may also provide authors a way to refer to content that does not exist in the source document (e.g., the ::before and ::after pseudo-elements give access to generated content).

A pseudo-element is made of two colons (::) followed by the name of the pseudo-element.

This :: notation is introduced by the current document in order to establish a discrimination between pseudo-classes and pseudo-elements. For compatibility with existing style sheets, user agents must also accept the previous one-colon notation for pseudo-elements introduced in CSS levels 1 and 2 (namely, :first-line, :first-letter, :before and :after). This compatibility is not allowed for the new pseudo-elements introduced in this specification.

Only one pseudo-element may appear per selector, and if present it must appear after the sequence of simple selectors that represents the subjects of the selector.

Note: A future version of this specification may allow multiple pseudo-elements per selector.

Pseudo-elements selectors:

The ::first-line pseudo-element

The ::first-line pseudo-element describes the contents of the first formatted line of an element.

CSS example:

p::first-line { text-transform: uppercase }

The above rule means "change the letters of the first line of every p element to uppercase". The selector p::first-line does not match any real document element. It does match a pseudo-element that conforming user agents will insert at the beginning of every p element.

Note that the length of the first line depends on a number of factors, including the width of the page, the font size, etc. Thus, an ordinary HTML paragraph such as:

<P>This is a somewhat long HTML
paragraph that will be broken into several
lines. The first line will be identified
by a fictional tag sequence. The other lines
will be treated as ordinary lines in the
paragraph.</P>

the lines of which happen to be broken as follows:

THIS IS A SOMEWHAT LONG HTML PARAGRAPH THAT
will be broken into several lines. The first
line will be identified by a fictional tag
sequence. The other lines will be treated as
ordinary lines in the paragraph.

This paragraph might be “rewritten” by user agents to include the fictional tag sequence for ::first-line. This fictional tag sequence helps to show how properties are inherited.

<P><P::first-line> This is a somewhat long HTML
paragraph that </P::first-line> will be broken into several
lines. The first line will be identified
by a fictional tag sequence. The other lines
will be treated as ordinary lines in the
paragraph.</P>

If a pseudo-element breaks up a real element, the desired effect can often be described by a fictional tag sequence that closes and then re-opens the element. Thus, if we mark up the previous paragraph with a span element:

<P><SPAN class="test"> This is a somewhat long HTML
paragraph that will be broken into several
lines.</SPAN> The first line will be identified
by a fictional tag sequence. The other lines
will be treated as ordinary lines in the
paragraph.</P>

the user agent could simulate start and end tags for span when inserting the fictional tag sequence for ::first-line.

<P><P::first-line><SPAN class="test"> This is a
somewhat long HTML
paragraph that will </SPAN></P::first-line><SPAN class="test"> be
broken into several
lines.</SPAN> The first line will be identified
by a fictional tag sequence. The other lines
will be treated as ordinary lines in the
paragraph.</P>

First formatted line definition in CSS

In CSS, the ::first-line pseudo-element can only have an effect when attached to a block-like container such as a block box, inline-block, table-caption, or table-cell.

The first formatted line of an element may occur inside a block-level descendant in the same flow (i.e., a block-level descendant that is not out-of-flow due to floating or positioning). For example, the first line of the DIV in

This line…

is the first line of the P (assuming that both P and DIV are block-level). The first line of a table-cell or inline-block cannot be the first formatted line of an ancestor element. Thus, in

Hello
Goodbye

etcetera

the first formatted line of the DIV is not the line "Hello".

Note: Note that the first line of the p in this fragment:

<p><br>First...

doesn’t contain any letters (assuming the default style for br in HTML 4). The word “First” is not on the first formatted line.

A UA should act as if the fictional start tags of the ::first-line pseudo-elements were nested just inside the innermost enclosing block-level element. (Since CSS1 and CSS2 were silent on this case, authors should not rely on this behavior.) For example, the fictional tag sequence for

<DIV>
  <P>First paragraph</P>
  <P>Second paragraph</P>
</DIV>

is

<DIV>
  <P><DIV::first-line><P::first-line>First paragraph</P::first-line></DIV::first-line></P>
  <P><P::first-line>Second paragraph</P::first-line></P>
</DIV>

The ::first-line pseudo-element is similar to an inline-level element, but with certain restrictions. The following CSS properties apply to a ::first-line pseudo-element: font properties, color property, background properties, ‘word-spacing’, ‘letter-spacing’, ‘text-decoration’, ‘vertical-align’, ‘text-transform’, ‘line-height’. UAs may apply other properties as well.

During CSS inheritance, the portion of a child element that occurs on the first line only inherits properties applicable to the ::first-line pseudo-element from the ::first-line pseudo-element. For all other properties inheritence is from the non-pseudo-element parent of the first line pseudo element. (The portion of a child element that does not occur on the first line always inherits from the parent of that child.)

The ::first-letter pseudo-element

The ::first-letter pseudo-element represents the first letter of an element, if it is not preceded by any other content (such as images or inline tables) on its line. The ::first-letter pseudo-element may be used for “initial caps” and "drop caps", which are common typographical effects.

Punctuation (i.e, characters defined in Unicode in the “open” (Ps), “close” (Pe), “initial” (Pi). “final” (Pf) and “other” (Po) punctuation classes), that precedes or follows the first letter should be included. UNICODE

The ::first-letter also applies if the first letter is in fact a digit, e.g., the “6” in “67 million dollars is a lot of money.”

Note: In some cases the ::first-letter pseudo-element should include more than just the first non-punctuation character on a line. For example, combining characters must be kept with their base character. Additionally, some languages may have specific rules about how to treat certain letter combinations. The UA definition of ::first-letter should include at least the default grapheme cluster as defined by UAX29 and may include more than that as appropriate. In Dutch, for example, if the letter combination “ij” appears at the beginning of an element, both letters should be considered within the ::first-letter pseudo-element. UAX29

If the letters that would form the ::first-letter are not in the same element, such as “‘T” in

<p>'<em>T...

, the UA may create a ::first-letter pseudo-element from one of the elements, both elements, or simply not create a pseudo-element.

Similarly, if the first letter(s) of the block are not at the start of the line (for example due to bidirectional reordering), then the UA need not create the pseudo-element(s).

The following CSS and HTML example illustrates how overlapping pseudo-elements may interact. The first letter of each P element will be green with a font size of ’24pt'. The rest of the first formatted line will be ‘blue’ while the rest of the paragraph will be ‘red’.

p { color: red; font-size: 12pt }
p::first-letter { color: green; font-size: 200% }
p::first-line { color: blue }
<P>Some text that ends up on two lines</P>

Assuming that a line break will occur before the word "ends", the fictional tag sequence for this fragment might be:

<P>
<P::first-line>
<P::first-letter>
S
</P::first-letter>ome text that
</P::first-line>
ends up on two lines
</P>

Note that the ::first-letter element is inside the ::first-line element. Properties set on ::first-line are inherited by ::first-letter, but are overridden if the same property is set on ::first-letter.

The first letter must occur on the first formatted line. For example, in this HTML fragment:

<p><br>First...

the first line doesn’t contain any letters and ::first-letter doesn’t match anything (assuming the default style for br in HTML 4). In particular, it does not match the “F” of “First.”