CSS Pseudo Element Selector

Pseudo-element selectors in CSS allow you to style specific parts of an element that aren't explicitly defined in your HTML. Think of them as "virtual" elements. While a standard selector targets a whole tag, a pseudo-element targets a specific sub-portion like the first letter of a paragraph or the space right before a heading.

Unlike pseudo-classes (like :hover), which represent a special state of an element, pseudo-elements target specific content within an element. The syntax for a pseudo-element is selector::pseudo-element { property: value; }. Note the use of double colons (::), which distinguishes pseudo-elements from pseudo-classes that use a single colon (:).

Common Mistake: Using a single colon (:before) instead of double colons (::before). While most browsers still support the single colon for backward compatibility with CSS2, modern CSS3 standards require double colons to differentiate pseudo-elements from pseudo-classes.

Here are some commonly used pseudo-elements:

  • ::first-line: Targets the first line of text in a block-level element. The "first line" is dynamic; it changes if the user resizes their browser window.
  • ::first-letter: Targets the very first letter of a block-level element, often used to create "Drop Caps" seen in newspaper articles.
  • ::before: Inserts content before the content of the selected element. This is widely used for adding icons, decorative flourishes, or decorative quotes.
  • ::after: Inserts content after the content of the selected element. Great for clearing floats or adding breadcrumb separators.
  • ::placeholder: Styles the hint text inside an <input> or <textarea> field.
  • ::selection: Styles the portion of an element that a user highlights with their mouse or touch.
Watch Out: When using ::before or ::after, you must include the content property, even if it is just an empty string (content: "";). Without this property, the pseudo-element will not render at all.

For example, to style the first line and first letter of all paragraphs to give them an editorial look, you could write:

CSS

/* Make the first line of every paragraph stand out */
p::first-line {
  color: #2c3e50;
  font-weight: bold;
  text-transform: uppercase;
}

/* Create a large 'Drop Cap' for the first letter */
p::first-letter {
  color: #e74c3c;
  font-size: 3rem;
  float: left;
  margin-right: 8px;
  line-height: 1;
}

In this example, the first line of every paragraph will be dark blue, bold, and uppercase. The first letter will be a large, red "drop cap" that the rest of the text wraps around.

Developer Tip: Use ::selection to match your website's branding. By default, highlights are usually blue, but changing it to your brand color (e.g., ::selection { background: #ffcc00; }) adds a nice touch of polish to your UI.

Real-World Example: Adding an External Link Icon

You can use ::after to automatically add a symbol to specific links, which helps with user experience by signaling that a link leads to an external site.

/* Add a "unicode" arrow after every link with the class 'external' */
a.external::after {
  content: " ↗";
  font-size: 0.8em;
  color: gray;
}

Pseudo-elements can be combined with other selectors, including class and ID selectors, to increase specificity. For instance, p.intro::first-letter would target the first letter only for paragraphs that have the class intro, leaving your standard body paragraphs untouched.

Best Practice: Use pseudo-elements for decorative content only. Since the content added via ::before or ::after is not part of the DOM, it may not be read by all screen readers. Always put essential information directly in your HTML.