In short
Add a decorative line under a heading, a quote mark before a testimonial, or style the first letter of a paragraph, all without extra HTML. Pseudo-elements create bits of the page from CSS.
Selectors like `::before` and `::after` that let you insert styled content into an element without adding it to the HTML. They are ideal for decorative presentation, but important information should generally remain in semantic HTML so it is available to assistive technologies and other consumers.

Think of it like this
Free toffee with your bill
The shop bill lists what you bought, but the shopkeeper adds a toffee on top that was never on the bill. ::before and ::after are those toffees: little extra boxes CSS adds before or after an element's content.
Watch it happen
Boxes CSS adds for you
1/4In the HTML, the h2 only contains its text.
The big ideas
What you need to know
::before and ::after
Create a child box at the start or end of the element. They need a content property, even if it's empty: content: "".
Style parts of text
::first-letter, ::first-line and ::selection style parts of the text without wrapping them in spans.
Form helpers
::placeholder styles hint text. ::marker styles the bullets and numbers in lists.
Double colon
Pseudo-elements use :: and pseudo-classes use :. One creates a part, the other picks a state.
See it in code
Walk through the code
1h2::after {2 content: "";3 display: block;4 width: 48px;5 height: 4px;6 margin-top: 8px;7 background: #ec4899; /* accent line under headings */8}9 10blockquote::before { content: "\201C"; font-size: 3rem; }11 12li::marker { color: #ec4899; }13::selection { background: #fbcfe8; }14input::placeholder { color: #9ca3af; }1/3content: "" creates the box. display: block lets width and height work, making a 48 by 4px line.
\201C is the opening curly quote character. Every h2 gets its accent line with zero extra HTML.
Save yourself the pain
Common mistakes
Oops
Forgetting content: "" and seeing nothing appear.
Do this instead
::before and ::after don't render at all without a content property.
Oops
Putting important text in content: "...".
Do this instead
Generated content isn't always read or copyable. Use it for decoration and keep real text in HTML.
Your mission
Decorate without markup
Quick check
You wrote h2::after { width: 40px; height: 3px; background: red; } but nothing shows. What's missing?
Go deeper
- 1Add a decorative icon or quote mark using `::before`/`::after`. Test the result on both a successful path and an invalid or unexpected input.
- 2Build a custom checkbox or tooltip arrow using pseudo-elements. Keep the first version small, then add one improvement after the core behavior works.
- 3Learn the required `content` property — without it, pseudo-elements won't render.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.