Pseudo-elements
::before and ::after — and then style it however you want.
.section-title::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 40px;
height: 3px;
background-color: #E50914;
}
input::placeholder {
color: rgba(255, 255, 255, 0.5);
font-style: italic;
}
Let me ask you something.
Have you ever seen a decorative line next to a heading? Or a quote with a big stylized quotation mark behind it? Or a form input where the placeholder text is a different color from the typed text?
None of that required extra HTML elements. It was all done with CSS pseudo-elements.
A pseudo-element lets you create and style a part of an element that does not actually exist in your HTML. You are essentially inserting invisible content from CSS alone and then styling it however you want.
The Double Colon Syntax
Pseudo-elements use two colons instead of one.
selector::pseudo-element {
property: value;
}
One colon is for pseudo-classes like :hover and :focus. Two colons are for pseudo-elements
like ::before and ::after. That is how you tell them apart.
::before
The ::before pseudo-element inserts content right before the content of an element. It sits inside the
element but before anything else in it.
The one rule is that it always needs a content property. Even if you do not want any text you still
write content: "" to make it appear.
Trending Now
.section-title { color: white; font-family: "Bebas Neue", sans-serif; font-size: 1.5rem; letter-spacing: 2px; background-color: #141414; padding: 16px; } .section-title::before { content: "▶ "; color: #E50914; }A red play icon now appears before the heading text without touching the HTML at all.
Here is what is happening.
::before — inserts generated content right before the text inside the element.
content: "▶ " — this is what gets inserted. It can be any text, symbol, or even an empty string.
Without this property the pseudo-element will not appear at all.
color: #E50914 — only the pseudo-element turns red. The heading text stays white because we targeted
::before specifically.
::after
The ::after pseudo-element works exactly like ::before but inserts content after the
element's content instead of before it.
Trending Now
.section-title { color: white; font-family: "Bebas Neue", sans-serif; font-size: 1.5rem; letter-spacing: 2px; position: relative; padding-bottom: 8px; display: inline-block; background-color: #141414; padding: 16px 16px 20px; } .section-title::after { content: ""; position: absolute; bottom: 8px; left: 16px; width: 40px; height: 3px; background-color: #E50914; border-radius: 2px; }A short red underline now appears below the heading. Clean, decorative, and not a single extra HTML element needed.
Here is what is happening step by step.
content: "" — empty string. We do not want any text. We just want the element to exist so we can style
it as a line.
position: absolute — takes the pseudo-element out of the normal flow so we can place it exactly where
we want. This works because the parent has position: relative.
bottom: 0 and left: 0 — places it right at the bottom left of the heading.
width: 40px and height: 3px — makes it a short wide flat line.
background-color: #E50914 — the line is red.
This short underline pattern is one of the most common uses of ::after in real projects. You will see it
on section headings, card titles, and feature labels everywhere.
The combination of position: relative on the parent and position: absolute on a
::before or ::after pseudo-element is the most powerful pattern these pseudo-elements
offer. It lets you place decorative elements anywhere around the parent without adding a single extra tag to your
HTML. Use this for underlines, badges, overlays, and decorative shapes.
A Practical Use — Overlay on Movie Cards
Here is something you will actually use. When someone hovers over a movie card you want a dark overlay to appear on
top of the image. You could add an extra div inside every card. But with ::after you can do it in pure
CSS with no extra HTML.
Hover over any card and a dark overlay appears on top of the image. Move away and it disappears.
Here is what is happening.
.movie-card::after — creates an invisible overlay covering the entire card. width: 100% and
height: 100% make it fill the card completely. background-color: rgba(0,0,0,0) means fully
transparent — invisible by default.
.movie-card:hover::after — this is combining a pseudo-class and a pseudo-element together. When the
card is hovered the overlay background changes to rgba(0,0,0,0.4) — a dark semi-transparent black. The
overlay appears.
position: relative on the card and position: absolute on ::after — the
overlay needs to cover exactly the card and nothing else. This combination makes that happen.
This is much cleaner than adding an extra div inside every single card in your HTML. One CSS rule handles all cards at once.
Using ::after for hover overlays on cards is a pattern used on virtually every streaming platform,
e-commerce site, and portfolio. It is clean, reusable, and keeps your HTML free of presentational elements. Any
time you think you need an extra empty div just for visual effect consider whether ::after can handle
it instead.
::placeholder
The ::placeholder pseudo-element styles the placeholder text inside input fields. By default placeholder
text is a light gray. You can change its color, size, and style.
The placeholder text is now a soft semi-transparent white and italic. When the user starts typing their text is fully
white and not italic because the actual input text is styled by the input selector — not the
::placeholder.
Here is what is happening.
input::placeholder — targets only the placeholder text inside the input. The actual typed text is not
affected.
color: rgba(255,255,255,0.5) — semi-transparent white. Subtle enough to feel like a hint rather than
real content.
font-style: italic — makes it clearly different from typed text so users know it is just a suggestion.
Styling ::placeholder is one of those small details that makes a form feel genuinely designed rather
than thrown together. On a dark background the default gray placeholder is often hard to read. A light
semi-transparent white or a muted version of your accent color works much better and keeps the form readable and
elegant.
Building the Netflix Clone
Let us bring all three pseudo-elements into our Netflix clone. The section headings get a red underline using
::after. The movie cards get a hover overlay using ::after. The email input gets a styled
placeholder using ::placeholder.
Unlimited movies, TV shows, and more.
Starts at USD 2.99. Cancel anytime.
Trending Now
Here is what every pseudo-element is doing.
.section-title::after — a short 40px red line sits under the heading.
display: inline-block on the parent makes the heading only as wide as its text so the underline does not
stretch the full page width.
.movie-card::after — an invisible overlay covers every card at all times. It is there but transparent
so you cannot see it.
.movie-card:hover::after — the moment you hover the overlay turns dark. The card does not fade —
instead a dark layer appears on top of it. This feels more cinematic than just opacity alone.
input::placeholder — the placeholder text is soft semi-transparent white and italic. Clearly a hint,
not real content.
Have anything to say about this lesson?
Your feedback helps improve these tutorials. If something was confusing or missing, let us know.