</>
Skip to content
CSS lessons (31/66)

CSS — Pseudo-elements

Two colons target pieces

Pseudo-classes (one colon) select states; pseudo-elements (two colons) select parts of an element — or create brand-new inline content.

p::first-line { font-weight: 700; }

::before and ::after — the workhorses

They insert a generated child at the start/end of an element. content is mandatory (use "" for empty):

.required::after {
    content: " *";
    color: crimson;
}

.quote::before { content: "“"; }
.quote::after  { content: "”"; }

The icon-badge pattern

.new-badge::after {
    content: "NEW";
    background: teal;
    color: white;
    font-size: 10px;
    padding: 2px 6px;
    border-radius: 999px;
    margin-left: 8px;
}

(A pill labeled NEW appears after matching elements — pure CSS, no HTML edits.)

Decorative shapes without extra markup

.tooltip {
    position: relative;
}
.tooltip::after {
    content: attr(data-tip);          /* pull text from an attribute! */
    position: absolute;
    bottom: 120%;
    left: 50%;
    transform: translateX(-50%);
    background: #111;
    color: white;
    padding: 6px 10px;
    border-radius: 4px;
    opacity: 0;
    transition: opacity 0.2s;
}
.tooltip:hover::after { opacity: 1; }

(Hovering reveals a dark tooltip whose text comes from data-tip.)

content: attr(data-x) reads any attribute — tiny templating system.

Text-part selectors

.article::first-letter {
    float: left;
    font-size: 3.2em;
    line-height: 0.9;
    padding-right: 8px;      /* drop cap! */
}

.article::first-line {
    letter-spacing: 0.5px;
}

(Classic magazine opening: oversized first letter with wrapped lines.)

::placeholder

input::placeholder {
    color: #94a3b8;
    font-style: italic;
}

::selection

::selection {
    background: #0d9488;
    color: white;
}

Brand-colored text highlighting — the detail people notice without knowing why.

::marker

List bullets/numbers:

li::marker {
    color: #0d9488;
    font-weight: 700;
}

before/after are real boxes

They participate in layout fully — flex items, positioned elements, grid children:

.divider {
    display: flex;
    align-items: center;
    gap: 12px;
}
.divider::before,
.divider::after {
    content: "";
    height: 1px;
    background: #ddd;
    flex: 1;                 /* lines grow outward from centered text */
}

(— Text — pattern used across countless sites.)

Rules to remember

  1. content required (even content: "")
  2. They render inside the element, before/after its actual children
  3. Not selectable by users, not read by most screen readers — never put essential info in them
  4. One of each per element (::before + ::after max)

Mini Practice

  1. Required-field asterisks via ::after on labels
  2. Drop-cap article opening
  3. attr()-driven tooltip on two different buttons
  4. Centered-text divider with growing side lines
  5. Brand ::selection + styled ::placeholder
  6. Teal list markers

Next: attr selectors →

Related Topics

Frequently Asked Questions about Pseudo-elements

What is Pseudo-elements in CSS?

Pseudo-elements is a fundamental concept in CSS. This lesson explains it step by step with clear examples, making it easy for beginners to understand.

How do I learn Pseudo-elements?

Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn Pseudo-elements.

Why is Pseudo-elements important in CSS?

Pseudo-elements is essential for CSS development. Understanding this concept will help you write better code and solve real-world problems more effectively.