Ensuring Pixel Perfect Spacing
Ensuring Pixel-Perfect Spacing
When reviewing a UI component, check these in order:
1. Spacing scale → All margins/padding are multiples of base unit (4px or 8px)
2. Optical alignment → Elements LOOK aligned, not just numerically aligned
3. Consistent gaps → Related items use same gap; unrelated use larger gap
4. Baseline alignment → Text in a row shares the same baseline
5. Edge alignment → Left/right edges of stacked elements line up
Fix in CSS using a spacing scale, never arbitrary values:
CSS/* Bad */ .card { padding: 13px 17px; margin-bottom: 22px; } /* Good — 4px base scale */ .card { padding: 12px 16px; margin-bottom: 24px; }
Progress:
- Step 1: Identify the base unit (4px or 8px grid) used by the design system
- Step 2: Measure actual rendered values (DevTools, not assumed CSS values)
- Step 3: Check spacing scale compliance
- Step 4: Check optical vs. mathematical alignment
- Step 5: Check consistency of similar elements across the page
- Step 6: Verify at multiple viewport widths
- Step 7: Document and fix deviations
Step 1: Identify the base unit
Look for the smallest recurring spacing value. Most systems use 4px or 8px. All spacing (padding, margin, gap) should be multiples of this unit: 4, 8, 12, 16, 24, 32, 48, 64.
Step 2: Measure actual values
Use browser DevTools computed styles, not source CSS — inherited styles, box-sizing, and line-height can shift the real rendered box. Measure with the DevTools ruler/overlay, not by eyeballing.
Step 3: Check spacing scale compliance
Flag any value not on the scale (e.g., 13px, 22px, 7px). These usually come from:
- Unintended inheritance (line-height adding phantom space)
- Hardcoded magic numbers instead of design tokens
- Icon/SVG internal padding not accounted for
Step 4: Optical vs. mathematical alignment
Numerically centered ≠ visually centered. Common corrections:
- Icons next to text: icons often need a 1-2px nudge due to visual weight distribution
- Triangular/pointed shapes (play buttons, arrows): need more optical padding on the "light" side
- Circles vs. squares: circles appear smaller than squares of the same dimension — size up circles slightly
- Text next to icons: align to icon's optical center, not bounding box center
Step 5: Consistency audit
Related elements (e.g., all card padding, all button heights) must use identical values. Build a quick table:
| Element | Expected | Actual | Match? |
|---|---|---|---|
| Card padding | 16px | 16px | ✅ |
| Button height | 40px | 38px | ❌ |
Step 6: Multi-viewport check
Spacing that's perfect at 1440px can break at 375px. Re-check at common breakpoints (375, 768, 1024, 1440) rather than assuming linear scaling.
Step 7: Fix and systematize
Replace magic numbers with tokens/variables so the fix prevents future drift:
CSS:root { --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-6: 24px; --space-8: 32px; }
Example 1:
Input: A card component with padding: 18px; margin-bottom: 15px; next to other cards using padding: 16px; margin-bottom: 24px;
Output:
CSS.card { padding: var(--space-4); /* 16px, matches siblings */ margin-bottom: var(--space-6); /* 24px, matches siblings */ }
Flag: original values were off-scale and inconsistent with sibling cards.
Example 2:
Input: A button with a left-aligned icon and text where the icon appears to sit 2px lower than the text baseline despite align-items: center.
Output: align-items: center centers bounding boxes, not visual mass. Fix with a manual nudge:
CSS.button-icon { transform: translateY(-1px); }
Verify by zooming to 400% and checking the icon's visual center against the text x-height.
Example 3: Input: Three stat cards where numbers are right-aligned but appear to form a jagged edge. Output: The issue is mismatched font-feature-settings (non-tabular numerals causing variable digit widths). Fix:
CSS.stat-number { font-variant-numeric: tabular-nums; }
- Always use a spacing scale/token system; never write raw pixel values in component code.
- Trust your eyes over the ruler for final judgment — optical alignment overrides mathematical alignment.
- Zoom to 200-400% in DevTools when checking fine alignment issues (sub-pixel rendering, icon nudges).
- Check
line-heightfirst when spacing looks "off" — it's the most common hidden cause of phantom spacing. - Use
outlineinstead ofborderwhen debugging to avoid affecting layout box size. - For icon/text alignment, compare against the text's x-height, not full line-height.
- Keep a consistent ratio between related and unrelated element spacing (e.g., 8px within a group, 24px+ between groups) so grouping is visually unambiguous.
- Trusting the CSS source over computed styles — inherited rules and box-sizing change actual rendered spacing.
- Centering icons mathematically and calling it done — visual weight requires manual correction.
- Mixing spacing scales (some components on 4px grid, others on 5px or 10px) — causes systemic misalignment.
- Ignoring line-height as a spacing contributor — it adds invisible space above/below text that stacks with margin.
- Checking only one viewport — spacing bugs often only appear at specific breakpoints.
- Using
marginon both parent and child when only one is needed — causes unpredictable additive spacing. - Assuming border-box everywhere — mixing
content-boxandborder-boxsilently changes effective padding math.