Skip to main content

CSS Debugging Workflow

Debugging CSS is a skill. This guide covers systematic approaches, DevTools mastery, and the specific patterns that resolve the most common CSS bugs — including WordPress-specific issues.

1. The Golden Rule: Work in DevTools First

Never edit your CSS file blindly. Always prototype fixes in browser DevTools first, then paste working code into your source.

  • Chrome: Press F12 → Elements tab → Styles panel.
  • Firefox: Has the best Grid and Flexbox inspector — use it for layout bugs.
  • Safari: Requires DevTools to be enabled in Preferences first.

2. The Outline Debug Technique

Apply colored outlines to every element to visualize the box model without affecting layout:

/* Paste this temporarily to see all boxes */
* { outline: 1px solid red; }

/* Color-coded by element type */
div { outline: 1px dashed red; }
p { outline: 1px dashed blue; }
span { outline: 1px dashed green; }
img { outline: 2px solid orange; }

/* Or use the CSS Debug bookmarklet concept */
* { background-color: rgba(255,0,0,0.05) !important; }

3. Reading the DevTools Styles Panel

Styles Panel Anatomy:
┌─────────────────────────────────────────────────────┐
│ element.style { ← Inline styles │
│ color: red; │
│ } │
│ │
│ .card { ← ──────────────── Your CSS file │
│ background: #1a1a1a; │
│ } │
│ │
│ ~~.card { color: blue; }~~ ← STRUCK THROUGH │
│ ← This rule was overridden by a more specific rule │
│ │
│ user agent stylesheet { ← Browser default │
│ display: block; │
│ } │
└─────────────────────────────────────────────────────┘

Struck-through rules are your primary debugging signal — they show exactly what was overridden and by what.

4. The Specificity Debugging Flowchart

My CSS rule doesn't apply. Why?

├── Is it struck through in DevTools?
│ YES → Specificity conflict
│ ├── Is winning rule from theme/plugin? → Increase specificity or use @layer
│ ├── Is winning rule using !important? → Match with !important (last resort)
│ └── Is winning rule inline style=""? → Inspect source, add your class

├── Not struck through, but not showing?
│ → CSS not loading
│ ├── Check: is the file enqueued?
│ ├── Check: browser cache (Ctrl+Shift+R)
│ └── Check: syntax error earlier in file (breaks rest of file)

└── Is the property inherited but overridden?
→ Use Computed tab → search the property → see where it comes from

5. The Computed Tab

The Computed tab shows the final resolved value of every property — accounting for all cascade, specificity, and inheritance:

  • Search for a property name (e.g., font-size) to see exactly what value applies.
  • Click the triangle next to any property to see which rule set that value and from which file.
  • Use this when struck-through analysis isn't enough.

6. Layout Debugging: Flex and Grid Inspectors

In Chrome:

  • Elements panel → Click the flex or grid badge next to an element → Visual overlay appears.

In Firefox (Superior):

  • Layout tab → Grid / Flex sections → Toggle line numbers, track sizes, area names.
/* Add temporary visual grid lines with this technique */
.debug-grid {
background-image:
linear-gradient(rgba(255,0,0,0.1) 1px, transparent 1px),
linear-gradient(90deg, rgba(255,0,0,0.1) 1px, transparent 1px);
background-size: 8px 8px;
}

7. Common Bug Index

Bug: Element Has Unexpected Height/Width

/* Diagnosis */
* { outline: 1px solid red; } /* Reveal box extents */

/* Common causes */
.fix-1 { box-sizing: border-box; } /* Padding adding to width */
.fix-2 { height: auto; } /* Height set when it shouldn't be */
.fix-3 { min-height: 0; min-width: 0; } /* Flex/Grid children not shrinking */

Bug: Sticky Not Working

/* Checklist */
.sticky { position: sticky; top: 0; } /* ← must have threshold */

/* Check parent for these — any of these BREAK sticky: */
.parent { overflow: hidden; } /* ← BREAKS sticky — remove */
.parent { overflow: auto; } /* ← BREAKS sticky — remove */
.parent { overflow: clip; } /* ← OK — use this instead */

/* Must have enough content to scroll */
/* Parent height must be taller than sticky element */

Bug: Z-index Not Working

/* z-index only works on positioned elements */
.above { position: relative; z-index: 10; } /* NOT: position: static */

/* Check for stacking context breakers — these create isolated z-index contexts: */
/* opacity < 1, transform, filter, will-change, isolation: isolate */
.parent { transform: translateZ(0); } /* Parent creates context — child z-index is scoped */

/* Debug stacking */
.element { isolation: isolate; } /* Create intentional stacking context */

Bug: Flexbox Item Overflows

.flex-child { min-width: 0; } /* Fix: flex children default to min-width: auto */
.flex-child { overflow: hidden; } /* Overflow hidden also resets flex min-width */

Bug: CSS Grid Item Not Sizing Correctly

/* Item doesn't expand */
.grid-item { min-width: 0; min-height: 0; } /* Same as flex */

/* Image not fitting grid cell */
.grid-item img { width: 100%; height: 100%; object-fit: cover; }

Bug: Margin Collapsing

/* Space between elements IS NOT the sum of margins */
/* Fix: use gap in flex/grid instead of margins */
.flex-col { display: flex; flex-direction: column; gap: 1.5rem; }

/* Or create BFC on parent */
.parent { display: flow-root; }

8. WordPress-Specific Debugging

Step 1: Identify the Conflicting Rule

1. Open DevTools → Elements
2. Click the styled element
3. Find your property in Styles panel — struck through?
4. Read the selector of the winning rule

Step 2: Beat the Conflicting Rule

/* Winning rule was: .site-header .nav a — specificity 0,2,1 */

/* Match: */
.site-header .main-nav a { color: var(--accent); }

/* Or outspecify: */
body .site-header .nav a { color: var(--accent); }

/* Safest pattern: chain-qualify the existing selector */
.site-header.site-header .nav a { color: var(--accent); } /* doubled class */

Step 3: Cache

Always do hard-refresh before debugging:
- Chrome/Firefox: Ctrl + Shift + R (Mac: Cmd + Shift + R)
- Clear plugin cache: LiteSpeed → Purge All
- Disable cache completely during dev: DevTools → Network → Disable cache ✓

9. CSS Validation

Check for syntax errors: Jigsaw CSS Validator

Common syntax errors that silently break everything after them:

/* Missing semicolon — breaks all rules after this one */
.card { background: red } /* ← missing ; */
.card { color: white; } /* ← this rule now doesn't work */

/* Unclosed bracket */
.card {
background: red;
/* ← missing closing } — breaks entire rest of file */

.next-rule { color: blue; } /* never applied */

10. AI-Assisted Debugging

Use Claude or ChatGPT to debug quickly:

My CSS rule doesn't work. Here is the element HTML:
[paste element HTML from DevTools → right-click → Copy outerHTML]

Here is the winning CSS rule (from DevTools struck-through):
[paste conflicting rule]

Here is my CSS:
[paste your rule]

How do I make my rule win without using !important?