Skip to main content

How Does This Badge Work? Understanding CSS Class Order and the relative-absolute Pattern

Β· 13 min read
Mahmut Salman
Software Developer

I copied the classes for a notification badge and it worked perfectly, but I had no idea what was happening! πŸ€” The classes were all jumbled: absolute -top-2 -right-2 bg-red-500 text-white... My mentor reorganized them in logical order, and suddenly everything clicked. Then I made a brilliant connection: relative + absolute is like max-w + mx-autoβ€”they're paired concepts that work together! This conversation taught me to see the patterns behind CSS.

The Working Code That Made No Sense​

Me (Backend Dev): I have this badge code that works:

<button className="relative">
Cart
<span className="absolute -top-2 -right-2 bg-red-500 text-white text-xs font-bold rounded-full h-6 w-6 flex items-center justify-center">
3
</span>
</button>

It creates a perfect notification badge! But the classes are all mixed upβ€”positioning, colors, sizing, centering. Can you reorganize them in a logical order so I can see what's happening at each step?

Breaking It Down Step-by-Step​

Frontend Mentor: Excellent question! Let me break down the badge classes in logical order so you can see what each step accomplishes:

Step 1: Positioning (Where Should It Be?)​

<span className="absolute -top-2 -right-2">
3
</span>

What each class does:

  • absolute β†’ "Position me relative to my nearest relative parent (the button)"
  • -top-2 β†’ "Move me UP by 8px from the top edge" (negative = goes outside parent)
  • -right-2 β†’ "Move me RIGHT by 8px from the right edge" (pops out at corner)

Visual result:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Cart │● ← Badge floats here
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Status: Badge is positioned at top-right corner βœ…

Step 2: Size (How Big Should the Circle Be?)​

<span className="absolute -top-2 -right-2 h-6 w-6">
3
</span>

What we added:

  • h-6 β†’ Height = 24px
  • w-6 β†’ Width = 24px

Visual result:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Cart β”‚β–‘ ← 24px Γ— 24px square
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Status: Badge is now a square box βœ…

Step 3: Shape (Make It a Circle!)​

<span className="absolute -top-2 -right-2 h-6 w-6 rounded-full">
3
</span>

What we added:

  • rounded-full β†’ "Make all corners fully rounded" (square β†’ circle)

How rounded-full works:

  • Sets border-radius: 9999px (huge radius)
  • On a square element (equal width/height), this creates a perfect circle
  • On a rectangle, it creates a pill shape

Visual result:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Cart │● ← Perfect circle!
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Status: Badge is now circular βœ…

Step 4: Background Color​

<span className="absolute -top-2 -right-2 h-6 w-6 rounded-full bg-red-500">
3
</span>

What we added:

  • bg-red-500 β†’ "Fill the circle with red color"

Visual result:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Cart β”‚πŸ”΄ ← Red circle appears!
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Status: We have a visible red circle βœ…

Step 5: Text Styling​

<span className="absolute -top-2 -right-2 h-6 w-6 rounded-full bg-red-500 text-white text-xs font-bold">
3
</span>

What we added:

  • text-white β†’ "Make the number white (for contrast against red)"
  • text-xs β†’ "Make the font extra small (12px)"
  • font-bold β†’ "Make it bold for better visibility"

Visual result:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Cart β”‚πŸ”΄ ← "3" appears but might not be centered
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ 3

Status: Number is visible but may be off-center ⚠️

Step 6: Center the Number (Final Polish!)​

<span className="absolute -top-2 -right-2 h-6 w-6 rounded-full bg-red-500 text-white text-xs font-bold flex items-center justify-center">
3
</span>

What we added:

  • flex β†’ "Turn on flexbox layout for this element"
  • items-center β†’ "Center content vertically"
  • justify-center β†’ "Center content horizontally"

Visual result:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Cart β”‚πŸ”΄ ← "3" is perfectly centered!
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β‘’

Status: Perfect notification badge! βœ…

Visual Progression Summary​

Frontend Mentor: Here's the entire transformation in one view:

Step 1: Position      β†’  β”Œβ”€β”€β”€β”€β”€β”€β”
β”‚ Cart │● (badge floats at top-right)
β””β”€β”€β”€β”€β”€β”€β”˜

Step 2: Size β†’ β”Œβ”€β”€β”€β”€β”€β”€β”
β”‚ Cart β”‚β–‘ (24px Γ— 24px square)
β””β”€β”€β”€β”€β”€β”€β”˜

Step 3: Shape β†’ β”Œβ”€β”€β”€β”€β”€β”€β”
β”‚ Cart │● (perfect circle)
β””β”€β”€β”€β”€β”€β”€β”˜

Step 4: Color β†’ β”Œβ”€β”€β”€β”€β”€β”€β”
β”‚ Cart β”‚πŸ”΄ (red circle)
β””β”€β”€β”€β”€β”€β”€β”˜

Step 5: Text β†’ β”Œβ”€β”€β”€β”€β”€β”€β”
β”‚ Cart β”‚πŸ”΄ (number inside, off-center)
β””β”€β”€β”€β”€β”€β”€β”˜ 3

Step 6: Center β†’ β”Œβ”€β”€β”€β”€β”€β”€β”
β”‚ Cart β”‚πŸ”΄β‘’ (perfectly centered!)
β””β”€β”€β”€β”€β”€β”€β”˜

Logical Order Summary​

The Six-Step Pattern:

  1. Position (where?) β†’ absolute -top-2 -right-2
  2. Size (how big?) β†’ h-6 w-6
  3. Shape (what shape?) β†’ rounded-full
  4. Color (what color?) β†’ bg-red-500
  5. Text (what does it say?) β†’ text-white text-xs font-bold
  6. Alignment (center the content) β†’ flex items-center justify-center

Me: This makes SO much more sense! The original order was all scrambled.

The Brilliant Connection: Paired CSS Patterns​

Me: Wait, so relative and absolute work together like max-w and mx-auto? They're usually used together?

Frontend Mentor: YES! That's a BRILLIANT connection! 🎯 You've discovered a fundamental CSS pattern!

Paired Concepts Comparison​

Pair 1: max-w-* + mx-auto (Centering)​

<div className="max-w-4xl mx-auto">
Content here
</div>

How they work together:

  • max-w-4xl β†’ "I have a maximum width constraint (896px)"
  • mx-auto β†’ "Now center me horizontally using that width"

Why they need each other:

  • ❌ mx-auto alone doesn't work (needs a width to center)
  • ❌ max-w-4xl alone won't center (sticks to left by default)
  • βœ… Together β†’ Centered container with constrained width

Visual:

Without mx-auto:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ [Content max-w-4xl] β”‚ ← Stuck to left
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

With mx-auto:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ [Content max-w-4xl] β”‚ ← Centered!
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Pair 2: relative + absolute (Positioning)​

<button className="relative">
Cart
<span className="absolute -top-2 -right-2">3</span>
</button>

How they work together:

  • relative (parent) β†’ "I'm the reference point for positioning"
  • absolute (child) β†’ "Position me relative to my nearest relative parent"

Why they need each other:

  • ❌ absolute alone positions relative to the entire page/viewport
  • ❌ relative alone doesn't do much visually (just creates positioning context)
  • βœ… Together β†’ Child positioned precisely relative to parent

Visual:

Without relative parent:
β”Œβ”€ Page ─────────────────────────────┐
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Cart β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ πŸ”΄β‘’ β”‚ ← Badge way over here!
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

With relative parent:
β”Œβ”€ Page ─────────────────────────────┐
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Cart β”‚πŸ”΄β‘’ ← Badge next to button β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Side-by-Side Pattern Comparison​

Me: So both are two-step patterns?

Frontend Mentor: Exactly! Let me show you the similarity:

Pattern Structure​

PatternFirst Class (Setup)Second Class (Action)Purpose
Centeringmax-w-* (constraint)mx-auto (center it)Horizontal centering
Positioningrelative (parent setup)absolute (child action)Custom positioning

The Mental Model​

Both follow this pattern:

  1. Setup (create the constraint/context)
  2. Action (use that setup to achieve the goal)

Centering:

Step 1: Set width constraint β†’ max-w-4xl
Step 2: Use auto margins to center β†’ mx-auto

Badge positioning:

Step 1: Make parent a reference point β†’ relative
Step 2: Position child relative to it β†’ absolute

The absolute Positioning Fallback​

Me: What happens if I forget relative on the parent?

Frontend Mentor: Great question! Let me show you:

Without relative Parent (Common Mistake)​

<button>
Cart
<span className="absolute -top-2 -right-2 bg-red-500 ...">3</span>
</button>

What happens:

  • The badge looks for the nearest positioned ancestor (relative, absolute, or fixed)
  • If none found, it positions relative to the <body> (entire page)!
  • Your badge ends up in a random corner of the screen

Visual result:

β”Œβ”€ Entire Page ─────────────────────┐
β”‚ πŸ”΄β”‚ ← Badge here!
β”‚ β‘’β”‚
β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Cart β”‚ ← Button here β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Why: The browser searches up the DOM tree for a positioning context:

<span absolute> β†’ <button> (not relative!) β†’ <div> (not relative!) β†’ <body> βœ… Use this!

With relative Parent (Correct)​

<button className="relative">
Cart
<span className="absolute -top-2 -right-2 bg-red-500 ...">3</span>
</button>

What happens:

  • The badge finds the nearest relative parent (the button)
  • Positions itself relative to the button
  • Badge appears exactly where you want it

Visual result:

β”Œβ”€ Entire Page ─────────────────────┐
β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Cart β”‚πŸ”΄β‘’ ← Badge here! β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Why: The browser searches up the DOM tree:

<span absolute> β†’ <button relative> βœ… Found it! Use this!

More Paired CSS Patterns​

Me: Are there other CSS pairs like this?

Frontend Mentor: Absolutely! Here are common paired patterns:

Pattern 3: flex + gap​

<div className="flex gap-4">
<div>Item 1</div>
<div>Item 2</div>
</div>

How they work together:

  • flex β†’ "I'm a flex container"
  • gap-4 β†’ "Add 16px spacing between my children"
  • ❌ gap doesn't work without flex or grid
  • βœ… Together β†’ Precise spacing between elements

Pattern 4: grid + grid-cols-*​

<div className="grid grid-cols-3 gap-4">
<div>1</div>
<div>2</div>
<div>3</div>
</div>

How they work together:

  • grid β†’ "I'm a grid container"
  • grid-cols-3 β†’ "Create 3 columns"
  • ❌ grid-cols-3 doesn't work without grid
  • βœ… Together β†’ Multi-column layout

Pattern 5: overflow-hidden + truncate​

<div className="w-32 overflow-hidden truncate">
Very long text that needs to be cut off
</div>

How they work together:

  • overflow-hidden β†’ "Hide content that exceeds boundaries"
  • truncate β†’ "Add ellipsis (...) to cut-off text"
  • ❌ truncate needs a width and overflow-hidden to work
  • βœ… Together β†’ Text ellipsis effect

Building a Complete Notification Badge​

Me: Can you show me the complete badge with all the concepts?

Frontend Mentor: Absolutely! Here's a production-ready example:

Complete Badge Implementation​

<div className="flex gap-4 p-8">
{/* Shopping Cart Badge */}
<button className="relative px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" />
</svg>
<span className="absolute -top-2 -right-2 h-6 w-6 rounded-full bg-red-500 text-white text-xs font-bold flex items-center justify-center">
3
</span>
</button>

{/* Notification Bell Badge */}
<button className="relative px-6 py-3 bg-gray-600 text-white rounded-lg hover:bg-gray-700">
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg>
<span className="absolute -top-2 -right-2 h-6 w-6 rounded-full bg-orange-500 text-white text-xs font-bold flex items-center justify-center">
12
</span>
</button>

{/* Messages Badge */}
<button className="relative px-6 py-3 bg-green-600 text-white rounded-lg hover:bg-green-700">
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z" />
</svg>
<span className="absolute -top-2 -right-2 h-6 w-6 rounded-full bg-purple-500 text-white text-xs font-bold flex items-center justify-center">
5
</span>
</button>
</div>

Breaking Down the Button Structure​

β”Œβ”€ Button (relative) ─────────┐
β”‚ β”‚
β”‚ [Cart Icon] β”‚πŸ”΄β‘’ ← Badge (absolute)
β”‚ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key classes explained:

Button:

  • relative β†’ Positioning context for badge
  • px-6 py-3 β†’ Padding for button size
  • bg-blue-600 β†’ Button background color
  • rounded-lg β†’ Rounded corners
  • hover:bg-blue-700 β†’ Darker on hover

Badge:

  • absolute -top-2 -right-2 β†’ Position at top-right corner
  • h-6 w-6 β†’ 24px circle
  • rounded-full β†’ Make it circular
  • bg-red-500 β†’ Red background
  • text-white text-xs font-bold β†’ White, small, bold text
  • flex items-center justify-center β†’ Center the number

Badge Variations​

Me: Can I customize the badge?

Frontend Mentor: Absolutely! Here are common variations:

Variation 1: Different Sizes​

{/* Small badge (h-5 w-5) */}
<span className="absolute -top-1 -right-1 h-5 w-5 rounded-full bg-red-500 text-white text-xs flex items-center justify-center">
9
</span>

{/* Medium badge (h-6 w-6) - Default */}
<span className="absolute -top-2 -right-2 h-6 w-6 rounded-full bg-red-500 text-white text-xs font-bold flex items-center justify-center">
9
</span>

{/* Large badge (h-8 w-8) */}
<span className="absolute -top-3 -right-3 h-8 w-8 rounded-full bg-red-500 text-white text-sm font-bold flex items-center justify-center">
99
</span>

Variation 2: Different Colors​

{/* Red (urgent) */}
<span className="... bg-red-500">3</span>

{/* Orange (warning) */}
<span className="... bg-orange-500">12</span>

{/* Blue (info) */}
<span className="... bg-blue-500">5</span>

{/* Green (success) */}
<span className="... bg-green-500">2</span>

Variation 3: Different Positions​

{/* Top-right (default) */}
<span className="absolute -top-2 -right-2 ...">3</span>

{/* Top-left */}
<span className="absolute -top-2 -left-2 ...">3</span>

{/* Bottom-right */}
<span className="absolute -bottom-2 -right-2 ...">3</span>

{/* Bottom-left */}
<span className="absolute -bottom-2 -left-2 ...">3</span>

Variation 4: Dot Indicator (No Number)​

{/* Just a red dot for notifications */}
<span className="absolute -top-1 -right-1 h-3 w-3 rounded-full bg-red-500 border-2 border-white">
</span>

Common Mistakes and Fixes​

Me: What mistakes should I avoid?

Frontend Mentor: Here are the most common pitfalls:

Mistake 1: Forgetting relative on Parent​

❌ Badge positions relative to page:
<button>
Cart
<span className="absolute -top-2 -right-2 ...">3</span>
</button>

βœ… Badge positions relative to button:
<button className="relative">
Cart
<span className="absolute -top-2 -right-2 ...">3</span>
</button>

Mistake 2: Not Making Badge Circular​

❌ Square badge (forgot rounded-full):
<span className="absolute -top-2 -right-2 h-6 w-6 bg-red-500 ...">
3
</span>

βœ… Circular badge:
<span className="absolute -top-2 -right-2 h-6 w-6 rounded-full bg-red-500 ...">
3
</span>

Mistake 3: Forgetting to Center the Number​

❌ Number not centered:
<span className="absolute -top-2 -right-2 h-6 w-6 rounded-full bg-red-500 text-white">
3
</span>

βœ… Number centered:
<span className="absolute -top-2 -right-2 h-6 w-6 rounded-full bg-red-500 text-white flex items-center justify-center">
3
</span>

Mistake 4: Using Different Width/Height​

❌ Oval shape (different dimensions):
<span className="h-6 w-8 rounded-full ...">3</span>

βœ… Perfect circle (equal dimensions):
<span className="h-6 w-6 rounded-full ...">3</span>

Key Takeaways​

Me: Let me summarize what I learned:

Frontend Mentor: Perfect! Here's the complete picture:

The Six-Step Badge Pattern:​

  1. Position β†’ absolute -top-2 -right-2 (where it goes)
  2. Size β†’ h-6 w-6 (how big)
  3. Shape β†’ rounded-full (make it circular)
  4. Color β†’ bg-red-500 (background)
  5. Text β†’ text-white text-xs font-bold (number styling)
  6. Center β†’ flex items-center justify-center (align content)

The Paired Pattern Discovery:​

Paired CSS Patterns:
1. max-w-* + mx-auto β†’ Centering
2. relative + absolute β†’ Custom positioning
3. flex + gap β†’ Spacing
4. grid + grid-cols-* β†’ Layout

The Mental Model:​

Two-step patterns:

  1. Setup (create context/constraint)
  2. Action (use that context)

Critical Rules:​

  • βœ… Parent must have relative for child absolute to work correctly
  • βœ… Equal width/height (h-6 w-6) needed for perfect circles with rounded-full
  • βœ… Use flex items-center justify-center to center content inside badge
  • βœ… Negative values (-top-2 -right-2) make badge pop outside parent

The Complete Badge Template:​

<button className="relative">
Your Content Here
<span className="absolute -top-2 -right-2 h-6 w-6 rounded-full bg-red-500 text-white text-xs font-bold flex items-center justify-center">
3
</span>
</button>

Me: This is brilliant! I not only understand how badges work now, but I also discovered a pattern that applies to other CSS concepts. The relative + absolute pairing makes so much sense when I think of it like max-w + mx-auto!

Frontend Mentor: That's advanced thinking! You're not just learning CSSβ€”you're seeing the patterns behind CSS. Once you recognize these paired concepts, you'll start seeing them everywhere. Keep making those connections! πŸš€


Have you discovered other CSS paired patterns? Share your findings in the comments! πŸ’¬