What CSS means by generated content is content that’s not physically present in the HTML markup. For example, when you create an ordered list, the numbers are not in the HTML. The browser generates and inserts them automatically, and it updates the sequence if items are added or removed. The ::before and ::after pseudo-elements perform a similar function, but go much further, allowing you to add just about any type of automatically generated content not only before list items, but before and after almost any HTML element.
The ::before and ::after pseudo-elements have been around for a long time. They’re part of the CSS2.1 specification (prefixed with a single colon rather than two), but Internet Explorer didn’t support them until IE 8. So, they went largely unnoticed. Now, they’re widely used for creating fun visual effects, such as ribbons and speech bubbles.
In this chapter, I’ll show you how to use the pseudo-elements to add text, images, and visual effects to various HTML elements, as well as how to generate complex numbered sequences.
In particular, you’ll learn how to do the following:
Note The code examples in this chapter use the CSS3 syntax, which is supported by the latest versions of all browsers. If you need to support IE 8, use the CSS2.1 single-colon versions (:before and :after) instead.
To add generated content to elements other than list items, you need to use the ::before or ::after pseudo-elements. As their names suggest, they insert content before or after an element. The inserted content is generated by one or more of the properties in Table 15-1.
The properties in Table 15-1 are not inherited, but they accept the inherit keyword as a value.
Table 15-1. Generated Content Properties
Defining the Content to be Inserted
The content property is extremely versatile. It accepts any of the following values:
Apart from the none and normal keywords, you can combine any of these values as a space-separated list to create complex content that is injected before or after an element.
Using the ::before and ::after pseudo-elements to insert images, text, or a combination of the two can be useful in situations where you need to label elements in a consistent way. For example, throughout this book points of interest are highlighted as Notes, Tips, or Cautions. The styles in image_text.html use the following three classes to mark up paragraphs in a similar way (see Figure 15-1):
Figure 15-1. The icons and bold text are automatically generated by the pseudo-elements
.note::before {
content: url(images/square_gray.gif) ' Note ';
font-weight: bold;
}
.tip::before {
content: url(images/square_gray.gif) ' Tip ';
font-weight: bold;
}
.caution::before {
content: url(images/square_gray.gif) ' Caution ';
font-weight: bold;
}
The ::before pseudo-element is appended to the selector in the same way as a pseudo-class. In this example, each selector is a class, but you can use any valid selector. The value specified for content begins with the path to the gray square image, followed by a space and the text in quotes. It doesn’t matter whether you use single or double quotes, as long as they’re a matching pair. I’ve added a space on either side of the text to separate it both from the icon and from the following text.
Normally the generated content is displayed inline, and the text inherits the same properties as the text in the element it’s being added to. But you can style the generated content like any other element.
The styles in text_image_display.html adapt the classes in the previous example like this:
.note::before {
content: url(images/square_gray.gif) ' Note ';
font-weight: bold;
display: block;
}
.tip::before {
content: url(images/square_gray.gif) ' Tip ';
font-weight: bold;
display: inline-block;
vertical-align: 24px;
}
.caution::before {
content: url(images/square_gray.gif) ' Caution ';
font-weight: bold;
color: #F8A809;
font-size: 24px;
font-family: Tahoma, Geneva, sans-serif;
}
As Figure 15-2 shows, the generated content in the note class becomes a block-level element occupying a separate line. In the tip class, it’s converted to an inline block and raised above the baseline. The caution class changes the color, font size, and font of the generated text.
Figure 15-2. The generated content can be styled independently of the element it’s added to
Caution The generated content doesn’t become part of the HTML markup, so don’t use ::before and ::after for essential content. It won’t be seen by users of older browsers.
Using the ::after pseudo-element to append generated content works exactly the same way. The styles in image_text_after.html identify the final paragraph using the :last-child pseudo-class. The ::after pseudo-element is appended to the selector to add a couple of images and some text, and style it to be centered on a separate line like this:
p:last-child::after {
content: url(images/flourish1.png) ' The End ' url(images/flourish2.png);
display: block;
text-align: center;
color: #B20000;
margin-top: 1em;
}
As Figure 15-3 shows, this adds a stylized “The End” at the foot of the page.
Figure 15-3. The ::after pseudo-element appends generated content at the end of an element
IE 8 doesn’t support the :last-child pseudo-class. For the preceding example to work in IE 8, you not only need to use the single-colon version of :after, but also to assign a class or ID to the last paragraph and use that as the selector, for example p.last:after.
Caution Although the ::before and ::after pseudo-elements can insert images before or after other HTML elements, they can’t add generated content to an image or to other replaced elements such as objects and videos. So, you can’t use them, for example, to add a caption after an image. They don’t work with form elements either.
Generating Content from an Attribute
The content property can inspect HTML tags, search for an attribute, and display the text value of the attribute. If the attribute doesn’t exist, the browser simply ignores it. To access the attribute, you insert the attribute name (without quotes) between the parentheses of attr().
This can be useful for displaying an external URL. You can use the attribute selector a[href^="http://"] to style external links differently from internal ones. So it’s just a question of using the ::after pseudo-element with the same selector like this (the code is in attribute.html):
a[href^="http://"]::after {
content: ' (' attr(href) ') ';
}
The content property uses attr(href) to extract the link’s URL. It’s surrounded on both sides by literal spaces and parentheses in quotes. As Figure 15-4 shows, the pseudo-element appends the URL in parentheses after an external link, but ignores an internal one.
Figure 15-4. The ::after pseudo-element automatically appends the URL to the external link
Generating Quotes Automatically
HTML has two elements that are intended to mark up quotations: <q> and <blockquote>. The first one is intended for short, inline quotations, whereas <blockquote> is reserved for lengthy quotations that are intended to be set off from the surrounding text.
You shouldn’t use quotation marks with <q> tags. The browser inserts them for you. For a long time, browsers failed to do so, but all modern browsers (including IE 8) now insert quotation marks correctly. However, IE 8+ uses single curly quotes, Firefox uses double curly quotes, and other browsers use double straight quotes.
The <blockquote> element> doesn’t automatically add quotation marks. You need to add them yourself if you want them.
With the help of the quotes property and the ::before and ::after pseudo-elements, you can control the generation of quotation marks not only for <q>, but also for any other element. What’s more, you can set up sequences to ensure that nested quotations are marked up correctly. For example, you can follow the American typographical practice of double quotes first, followed by single ones for nested quotations. Alternatively, you can use the British convention of single quotes followed by double ones. Or if you’re working with another language, you can use the correct glyphs.
The quotes property expects a space-separated list of pairs of opening and closing quotation marks. If you specify multiple pairs, they’re used in sequence depending on how deep the quotations are nested. The browser automatically keeps track of the level of nesting.
To generate curly quotes or other types of quotation marks, use the hexadecimal codes listed in Table 15-2.
Table 15-2. Hexadecimal Codes for Generating Quotation Marks
Hexadecimal Code | Mark | Description |
---|---|---|
2018 | ‘ | Left single quotation mark |
2019 | ’ | Right single quotation mark |
201C | “ | Left double quotation mark |
201D | ” | Right double quotation mark |
201E | „ | Double low-9 quotation mark |