- 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
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
- Images are inline by default - They respect text baseline, creating extra vertical space
- SVG icons create inline gaps - SVGs also default to inline display
- 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
blockclass to<img> - ✅ Reset
fontSize: '1rem'for "No Image" text - ✅ Added
flex items-center justify-centerto 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>hasdisplay: inline - Inline elements align to the text baseline
- This creates a small gap below the image (descender space)
Font Size Zero Trick
- Setting
fontSize: 0on 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: blockremoves 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
- ✅ Go to
/shop - ✅ Check product images - should fill containers completely
- ✅ No whitespace at bottom of images
- ✅ Hover effects should work smoothly
Product Page Test
- ✅ Click any product
- ✅ Product image should fill container
- ✅ No whitespace at bottom
- ✅ 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: 0utility - 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:
- Container:
style={{ fontSize: 0 }} - Image:
className="block ..." - 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!