Pseudo-Elements
Pseudo-elements are similar in syntax to pseudo-classes, but they do something fundamentally different. Where pseudo-classes target an element in a particular state, pseudo-elements target a part of an element — or insert generated content that does not exist in the HTML.
Pseudo-elements use a double colon (::) prefix.
::before and ::after
Section titled “::before and ::after”::before inserts generated content before the element’s actual content. ::after inserts generated content after it. Neither element appears in the HTML — they are created entirely by CSS.
Both require the content property. Without content, the pseudo-element does not render.
.tour-name::before { content: "→ "; color: #2c4a1e;}Result: every .tour-name element now visually displays an arrow before its text — without touching the HTML.
/* Decorative separator after sections */section::after { content: ""; display: block; width: 60px; height: 3px; background-color: #2c4a1e; margin-top: 2rem;}When content: "" is an empty string, the pseudo-element renders as a visible box — useful for decorative shapes and dividers. The element still needs display: block (or similar) and dimensions to be visible.
::first-line
Section titled “::first-line”Targets only the first rendered line of a block element. The “first line” is determined by the browser — it changes as the viewport width changes.
article > p:first-child::first-line { font-weight: bold; font-size: 1.1rem;}This is useful for drop-cap article intros or styled opening lines. You cannot reliably control exactly how many words are in the “first line.”
::first-letter
Section titled “::first-letter”Targets only the first letter of a block element. Classic use: the drop-cap effect.
article > p:first-child::first-letter { font-size: 3rem; float: left; line-height: 0.8; margin-right: 0.1em; color: #2c4a1e;}float: left is a legacy CSS property originally designed for text-wrap layout — wrapping text around images. It has been largely replaced by Flexbox and Grid for general layout. The drop-cap pattern is one of the few cases where float is still the standard approach: it pulls the enlarged letter out of the flow and lets the remaining text wrap beside it.
::placeholder
Section titled “::placeholder”Targets the placeholder text inside <input> and <textarea> elements.
input::placeholder,textarea::placeholder { color: #aaa; font-style: italic;}Placeholder text is often too light or too stylistically similar to actual input text. ::placeholder lets you distinguish it clearly.
Pseudo-elements vs pseudo-classes
Section titled “Pseudo-elements vs pseudo-classes”| Pseudo-class | Pseudo-element | |
|---|---|---|
| Syntax | :hover, :focus | ::before, ::after |
| Targets | State of the whole element | A part of the element |
| Examples | :hover, :first-child | ::before, ::placeholder |
You will sometimes see pseudo-elements written with a single colon (:before, :after) in older code. This is legacy syntax from CSS2. The double colon (::) is the correct modern syntax — use it.
The content property
Section titled “The content property”content is required for ::before and ::after. It accepts:
- A text string:
content: "→ "— renders that text - An empty string:
content: ""— creates an empty box (for decorative shapes) - A URL:
content: url(icon.svg)— embeds an image noneornormal— removes the pseudo-element
content has no effect on any element other than ::before and ::after.
Exercise
Section titled “Exercise”Add pseudo-element styles to your Summit Trail Outfitters pages:
- Decorative prefix on tour names — add a character before each tour card heading:
.tour-name::before { content: "▶ "; color: #2c4a1e; font-size: 0.8em;}Note: .tour-name is used here as a teaching example. When you style the full STO site in Module 07, the heading class is .tour-card-title and the decorative prefix rule is not included — it is a technique demonstration, not a production rule.
- Style form placeholder text — make placeholders visually distinct from entered text:
input::placeholder,textarea::placeholder { color: #aaa; font-style: italic;}- Optional drop-cap — if your blog article page has a long article intro, add a drop-cap to the first paragraph:
.article-body > p:first-child::first-letter { font-size: 3.5rem; float: left; line-height: 0.75; margin-right: 0.1em; color: #2c4a1e;}To test this, add class="article-body" to the <div> wrapping your article text in blog-article.html. Note: the full STO stylesheet in Module 07 uses .article-content for this wrapper, not .article-body, and does not include a drop-cap rule — this is a technique demonstration only.
Inspect the result in DevTools. In the Elements panel, expand an element that has ::before or ::after — you will see the pseudo-element listed as a child of the targeted element.
- Pseudo-elements use
::(double colon) and target a part of an element, not the whole element. ::beforeand::afterinsert generated content; they require thecontentproperty.- An empty
content: ""creates an invisible box — add dimensions anddisplay: blockto make it visible. ::first-lineand::first-lettertarget typographic parts of block content.::placeholderstyles the placeholder text in form inputs.- Single-colon syntax (
:before) is legacy — use::in new code.