Files
WooNooW/INLINE_SPACING_FIX.md
Dwindi Ramadhana f397ef850f feat: Add product images support with WP Media Library integration
- Add WP Media Library integration for product and variation images
- Support images array (URLs) conversion to attachment IDs
- Add images array to API responses (Admin & Customer SPA)
- Implement drag-and-drop sortable images in Admin product form
- Add image gallery thumbnails in Customer SPA product page
- Initialize WooCommerce session for guest cart operations
- Fix product variations and attributes display in Customer SPA
- Add variation image field in Admin SPA

Changes:
- includes/Api/ProductsController.php: Handle images array, add to responses
- includes/Frontend/ShopController.php: Add images array for customer SPA
- includes/Frontend/CartController.php: Initialize WC session for guests
- admin-spa/src/lib/wp-media.ts: Add openWPMediaGallery function
- admin-spa/src/routes/Products/partials/tabs/GeneralTab.tsx: WP Media + sortable images
- admin-spa/src/routes/Products/partials/tabs/VariationsTab.tsx: Add variation image field
- customer-spa/src/pages/Product/index.tsx: Add gallery thumbnails display
2025-11-26 16:18:43 +07:00

6.1 KiB

Inline Spacing Fix - The Real Root Cause

The Problem

Images were not filling their containers, leaving whitespace at the bottom. This was NOT a height issue, but an inline element spacing issue.

Root Cause Analysis

  1. Images are inline by default - They respect text baseline, creating extra vertical space
  2. SVG icons create inline gaps - SVGs also default to inline display
  3. Line-height affects layout - Parent containers with text create baseline alignment issues

Visual Evidence

┌─────────────────────┐
│                     │
│      IMAGE          │
│                     │
│                     │
└─────────────────────┘
  ↑ Whitespace gap here (caused by inline baseline)

The Solution

Three Key Fixes

1. Make Images Block-Level

// Before (inline by default)
<img className="w-full h-full object-cover" />

// After (block display)
<img className="block w-full h-full object-cover" />

2. Remove Inline Whitespace from Container

// Add fontSize: 0 to parent
<div style={{ fontSize: 0 }}>
  <img className="block w-full h-full object-cover" />
</div>

3. Reset Font Size for Text Content

// Reset fontSize for text elements inside
<div style={{ fontSize: '1rem' }}>
  No Image
</div>

Implementation

ProductCard Component

All 4 layouts fixed:

// Classic, Modern, Boutique, Launch
<div className="relative w-full h-64 overflow-hidden bg-gray-100" 
     style={{ fontSize: 0 }}>
  {product.image ? (
    <img
      src={product.image}
      alt={product.name}
      className="block w-full h-full object-cover object-center"
    />
  ) : (
    <div className="w-full h-full flex items-center justify-center text-gray-400" 
         style={{ fontSize: '1rem' }}>
      No Image
    </div>
  )}
</div>

Key changes:

  • Added style={{ fontSize: 0 }} to container
  • Added block class to <img>
  • Reset fontSize: '1rem' for "No Image" text
  • Added flex items-center justify-center to button with Heart icon

Product Page

Same fix applied:

<div className="relative w-full h-96 rounded-lg overflow-hidden bg-gray-100" 
     style={{ fontSize: 0 }}>
  {product.image ? (
    <img
      src={product.image}
      alt={product.name}
      className="block w-full h-full object-cover object-center"
    />
  ) : (
    <div className="w-full h-full flex items-center justify-center text-gray-400" 
         style={{ fontSize: '1rem' }}>
      No image
    </div>
  )}
</div>

Why This Works

The Technical Explanation

Inline Elements and Baseline

  • By default, <img> has display: inline
  • Inline elements align to the text baseline
  • This creates a small gap below the image (descender space)

Font Size Zero Trick

  • Setting fontSize: 0 on parent removes whitespace between inline elements
  • This is a proven technique for removing gaps in inline layouts
  • Text content needs fontSize: '1rem' reset to be readable

Block Display

  • display: block removes baseline alignment
  • Block elements fill their container naturally
  • No extra spacing or gaps

Files Modified

1. ProductCard.tsx

Location: customer-spa/src/components/ProductCard.tsx

Changes:

  • Classic layout (line ~43)
  • Modern layout (line ~116)
  • Boutique layout (line ~183)
  • Launch layout (line ~247)

Applied to all:

  • Container: style={{ fontSize: 0 }}
  • Image: className="block ..."
  • Fallback text: style={{ fontSize: '1rem' }}

2. Product/index.tsx

Location: customer-spa/src/pages/Product/index.tsx

Changes:

  • Product image container (line ~121)
  • Same pattern as ProductCard

Testing Checklist

Visual Test

  1. Go to /shop
  2. Check product images - should fill containers completely
  3. No whitespace at bottom of images
  4. Hover effects should work smoothly

Product Page Test

  1. Click any product
  2. Product image should fill container
  3. No whitespace at bottom
  4. Image should be 384px tall (h-96)

Browser Test

  • Chrome
  • Firefox
  • Safari
  • Edge

Best Practices Applied

Global CSS Recommendation

For future projects, add to global CSS:

img {
  display: block;
  max-width: 100%;
}

svg {
  display: block;
}

This prevents inline spacing issues across the entire application.

Why We Used Inline Styles

  • Tailwind doesn't have a font-size: 0 utility
  • Inline styles are acceptable for one-off fixes
  • Could be extracted to custom Tailwind class if needed

Comparison: Before vs After

Before

<div className="relative w-full h-64">
  <img className="w-full h-full object-cover" />
</div>

Result: Whitespace at bottom due to inline baseline

After

<div className="relative w-full h-64" style={{ fontSize: 0 }}>
  <img className="block w-full h-full object-cover" />
</div>

Result: Perfect fill, no whitespace


Key Learnings

1. Images Are Inline By Default

Always remember that <img> elements are inline, not block.

2. Baseline Alignment Creates Gaps

Inline elements respect text baseline, creating unexpected spacing.

3. Font Size Zero Trick

Setting fontSize: 0 on parent is a proven technique for removing inline gaps.

4. Display Block Is Essential

For images in containers, always use display: block.

5. SVGs Have Same Issue

SVG icons also need display: block to prevent spacing issues.


Summary

Problem: Whitespace at bottom of images due to inline element spacing

Root Cause: Images default to display: inline, creating baseline alignment gaps

Solution:

  1. Container: style={{ fontSize: 0 }}
  2. Image: className="block ..."
  3. Text: style={{ fontSize: '1rem' }}

Result: Perfect image fill with no whitespace!


Credits

Thanks to the second opinion for identifying the root cause:

  • Inline SVG spacing
  • Image baseline alignment
  • Font-size zero technique

This is a classic CSS gotcha that many developers encounter!