Back to top
Programmers Picnic by Champak Roy

CSS :root, ::before, ::after and All Important :: Pseudo Elements

A complete Level 0 to Infinity lesson for total beginners. We will start with ordinary CSS selectors, then learn CSS variables, pseudo-classes, pseudo-elements, decorations, badges, tooltips, forms, lists, selections, dialogs, and professional design patterns.

Start from Level 0 Jump to :: Reference

0. Level 0: What is CSS?

HTML creates the structure of a page. CSS controls the look of the page.

HTML

HTML says what exists on the page.

<h1>Learn CSS</h1>
<p>CSS makes pages beautiful.</p>

CSS

CSS says how those things should look.

h1 {
  color: orange;
}

p {
  color: #333;
}

CSS is like the dress, decoration, lighting, spacing, and animation system of a webpage.

1. What is a selector?

A CSS selector selects something from HTML.

<h1>Programmers Picnic</h1>
<p class="intro">Learn step by step.</p>
<button id="startBtn">Start</button>
h1 {
  color: orange;
}

.intro {
  color: brown;
}

#startBtn {
  background: orange;
}
Selector Meaning Example
h1 Selects all h1 tags h1 { color: orange; }
.intro Selects class intro .intro { color: brown; }
#startBtn Selects id startBtn #startBtn { background: orange; }
:hover Selects a state button:hover { ... }
::before Selects a virtual part before content h1::before { ... }

2. What is :root?

:root means the top-level element of the webpage. In normal HTML pages, it usually means the <html> element.

:root {
  --primary: #d97706;
  --background: #fff7ed;
  --text: #241407;
}

The most common use of :root is to store CSS variables.

:root uses one colon because it is a pseudo-class, not a pseudo-element.

3. CSS Variables

CSS variables are reusable values. You define them once and use them many times.

:root {
  --bg: #fff7ed;
  --card: #ffffff;
  --primary: #d97706;
  --text: #241407;
  --radius: 22px;
}

body {
  background: var(--bg);
  color: var(--text);
}

.card {
  background: var(--card);
  border-radius: var(--radius);
}

button {
  background: var(--primary);
}

Change the value in one place and the whole design changes everywhere.

Why professionals use CSS variables

  • Easy theme control
  • Dark mode and light mode
  • Consistent colors
  • Consistent spacing
  • Better maintainability

4. Pseudo-classes use one colon

A pseudo-class selects an element in a special state or condition.

button:hover {
  background: black;
}

input:focus {
  border-color: orange;
}

li:first-child {
  font-weight: bold;
}

li:last-child {
  color: red;
}

li:nth-child(even) {
  background: #fff7ed;
}
Pseudo-class Meaning
:hover When mouse is over the element
:focus When input or button is focused
:first-child Selects the first child
:last-child Selects the last child
:nth-child() Selects by position or pattern
:root Selects the root element

5. Pseudo-elements use double colon

A pseudo-element selects a special part of an element or creates a virtual part of an element.

h1::before {
  content: "Start ";
}

h1::after {
  content: " End";
}

p::first-letter {
  font-size: 48px;
}

p::first-line {
  font-weight: bold;
}
Real Text

In the demo above, the HTML contains only Real Text. The words before and after are added by CSS.

Pseudo-elements are not real HTML tags. They are CSS-created or CSS-selected parts.

6. Deep lesson: ::before and ::after

::before creates a virtual element before the actual content. ::after creates a virtual element after the actual content.

<h2 class="lesson-title">CSS Lesson</h2>
.lesson-title::before {
  content: "Start: ";
  color: orange;
}

.lesson-title::after {
  content: " Done!";
  color: green;
}

Visual example

Professional Heading
.underline-demo::after {
  content: "";
  display: block;
  height: 6px;
  width: 100%;
  background: orange;
  border-radius: 999px;
  margin-top: 8px;
}

Badge example

Python Beginner Course

This card has a badge created by ::before. No extra HTML was needed for the badge.

.badge-demo {
  position: relative;
}

.badge-demo::before {
  content: "Featured";
  position: absolute;
  top: 14px;
  right: 14px;
  background: orange;
  color: white;
  padding: 5px 10px;
  border-radius: 999px;
}

7. The content property

For ::before and ::after, the content property is extremely important. Without it, the pseudo-element usually will not appear.

No content

.box::after {
  width: 100px;
  height: 5px;
  background: orange;
}

With content

.box::after {
  content: "";
  display: block;
  width: 100px;
  height: 5px;
  background: orange;
}

Different types of content

Code Meaning
content: ""; Empty content, useful for shapes and decorations
content: "New"; Text content
content: "→"; Symbol content
content: attr(data-tip); Content from an HTML attribute
content: counter(item); Content from CSS counters

8. Professional uses of ::before and ::after

Icons

Add symbols before links, buttons, or list items.

a::before {
  content: "🔗 ";
}

Underline

Create modern animated underlines.

h2::after {
  content: "";
  display: block;
  height: 4px;
}

Badges

Add labels like New, Featured, Popular.

.card::before {
  content: "New";
}

Background layers

Create decorative circles, gradients, and glows.

.hero::before {
  content: "";
  position: absolute;
}

Tooltips

Show small help text on hover.

.help::after {
  content: attr(data-tip);
}

Watermarks

Add faint background text.

.card::after {
  content: "CSS";
}

9. All important :: pseudo-elements

These are not HTML tags. They are CSS pseudo-elements. Some work everywhere, some work only in special cases, and some have limited browser support.

Pseudo-element Use Simple example
::before Adds virtual content before element content h1::before { content: "★ "; }
::after Adds virtual content after element content h1::after { content: " ✓"; }
::first-letter Styles the first letter of text p::first-letter { font-size: 50px; }
::first-line Styles the first visible line of text p::first-line { font-weight: bold; }
::selection Styles text when selected by mouse ::selection { background: orange; }
::marker Styles list bullets or numbers li::marker { color: orange; }
::placeholder Styles input placeholder text input::placeholder { color: orange; }
::file-selector-button Styles the button inside file input input::file-selector-button { ... }
::backdrop Styles the background behind a dialog or fullscreen element dialog::backdrop { background: black; }
::cue Styles captions in video tracks ::cue { color: yellow; }
::part() Styles exposed parts of Web Components my-card::part(title) { ... }
::slotted() Styles slotted content inside Shadow DOM ::slotted(span) { ... }
::spelling-error Styles browser spelling errors where supported ::spelling-error { color: red; }
::grammar-error Styles browser grammar errors where supported ::grammar-error { color: blue; }
::view-transition Used in View Transitions API ::view-transition { ... }
::view-transition-group() Styles a transition group ::view-transition-group(root) { ... }
::view-transition-image-pair() Styles old and new transition image pair ::view-transition-image-pair(root) { ... }
::view-transition-old() Styles old visual snapshot in a transition ::view-transition-old(root) { ... }
::view-transition-new() Styles new visual snapshot in a transition ::view-transition-new(root) { ... }
For daily web design, the most important ones are ::before, ::after, ::first-letter, ::first-line, ::selection, ::marker, ::placeholder, ::file-selector-button, and ::backdrop.

10. Live examples of important :: pseudo-elements

::first-letter

Cascading Style Sheets can turn plain writing into a professional article layout. The first letter here is designed using CSS only.

.first-letter-demo::first-letter {
  font-size: 3.4rem;
  float: left;
  padding-right: 8px;
  color: orange;
  font-weight: 900;
}

::first-line

This paragraph has a first line that looks different from the rest of the paragraph. Resize the browser and observe that the first visible line can change.

.first-line-demo::first-line {
  color: orange;
  font-weight: 900;
}

::marker

  • CSS variables
  • Pseudo-classes
  • Pseudo-elements
li::marker {
  color: orange;
  font-size: 1.3em;
  content: "★ ";
}

11. Form pseudo-elements

::placeholder

input::placeholder {
  color: orange;
  opacity: 0.7;
}

::file-selector-button

input[type="file"]::file-selector-button {
  border: 0;
  padding: 10px 14px;
  margin-right: 12px;
  border-radius: 999px;
  background: orange;
  color: white;
  font-weight: 800;
}

12. Tooltip using ::after and attr()

Move your mouse over this button:

Hover me

<span class="tooltip-demo" data-tip="This text comes from data-tip">
  Hover me
</span>
.tooltip-demo {
  position: relative;
}

.tooltip-demo::after {
  content: attr(data-tip);
  position: absolute;
  left: 50%;
  bottom: 135%;
  transform: translateX(-50%);
  background: #111827;
  color: white;
  padding: 8px 12px;
  border-radius: 10px;
  white-space: nowrap;
  opacity: 0;
}

.tooltip-demo:hover::after {
  opacity: 1;
}

13. Dialog and ::backdrop

::backdrop styles the area behind a dialog box.

Dialog Box

The dark blurry background behind this box is styled with dialog::backdrop.

dialog::backdrop {
  background: rgba(36, 20, 7, 0.55);
  backdrop-filter: blur(5px);
}

14. Common mistakes

Mistake 1: Forgetting content

Bad

.box::after {
  display: block;
  width: 100px;
  height: 5px;
  background: orange;
}

Good

.box::after {
  content: "";
  display: block;
  width: 100px;
  height: 5px;
  background: orange;
}

Mistake 2: Forgetting position: relative

Bad

.card::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
}

Good

.card {
  position: relative;
}

.card::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
}

Mistake 3: Expecting ::before and ::after on every tag

Pseudo-elements may not work reliably on replaced elements like img, input, and br.

Better method: wrap the element inside a normal element, then apply ::before or ::after to the wrapper.
<div class="image-wrap">
  <img src="photo.jpg" alt="Photo">
</div>
.image-wrap {
  position: relative;
}

.image-wrap::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 4px solid orange;
}

15. Mini projects

Project 1: Heading underline

<h2 class="heading">Learn Python</h2>
.heading::after {
  content: "";
  display: block;
  width: 90px;
  height: 5px;
  background: orange;
  border-radius: 999px;
  margin-top: 10px;
}

Project 2: Button arrow

<a class="arrow-btn" href="#">Start Learning</a>
.arrow-btn::after {
  content: " →";
}

Project 3: Course card badge

<div class="course-card">
  <h2>AI Beginner Course</h2>
  <p>Start from zero.</p>
</div>
.course-card {
  position: relative;
}

.course-card::before {
  content: "New";
  position: absolute;
  top: 12px;
  right: 12px;
  background: orange;
  color: white;
  padding: 5px 10px;
  border-radius: 999px;
}

16. Final memory map

Selector Colon type Meaning
:root Single colon Root element, usually used for CSS variables
:hover Single colon Mouse is over the element
:focus Single colon Element is focused
:nth-child() Single colon Selects children by position or pattern
::before Double colon Creates virtual content before
::after Double colon Creates virtual content after
::first-letter Double colon Styles first letter
::first-line Double colon Styles first visible line
::selection Double colon Styles selected text
::marker Double colon Styles list marker
::placeholder Double colon Styles placeholder text
::file-selector-button Double colon Styles file input button
::backdrop Double colon Styles background behind dialog/fullscreen
Main rule: one colon usually means a state or condition. Double colon usually means a part of an element or a virtual element.

17. Practice assignments

  1. Create a page theme using :root variables.
  2. Create a heading underline using ::after.
  3. Create a card badge using ::before.
  4. Create a list with check marks using li::before.
  5. Create an input with styled ::placeholder.
  6. Create a file upload button using ::file-selector-button.
  7. Create a tooltip using attr(data-tip) and ::after.
  8. Create a quote paragraph using ::first-letter.
  9. Create custom bullet points using ::marker.
  10. Create a dialog with styled ::backdrop.