- 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
5.1 KiB
Real Fix - Different Approach
Problem Analysis
After multiple failed attempts with aspect-ratio and padding-bottom techniques, the root issues were:
- CSS aspect-ratio property - Unreliable with absolute positioning across browsers
- Padding-bottom technique - Not rendering correctly in this specific setup
- Missing slug parameter - Backend API didn't support filtering by product slug
Solution: Fixed Height Approach
Why This Works
Instead of trying to maintain aspect ratios dynamically, use fixed heights with object-cover:
// Simple, reliable approach
<div className="w-full h-64 overflow-hidden bg-gray-100">
<img
src={product.image}
alt={product.name}
className="w-full h-full object-cover object-center"
/>
</div>
Benefits:
- ✅ Predictable rendering
- ✅ Works across all browsers
- ✅ No complex CSS tricks
- ✅
object-coverhandles image fitting - ✅ Simple to understand and maintain
Heights Used
- Classic Layout:
h-64(256px) - Modern Layout:
h-64(256px) - Boutique Layout:
h-80(320px) - taller for elegance - Launch Layout:
h-64(256px) - Product Page:
h-96(384px) - larger for detail view
Changes Made
1. ProductCard Component ✅
File: customer-spa/src/components/ProductCard.tsx
Changed:
// Before (didn't work)
<div style={{ paddingBottom: '100%' }}>
<img className="absolute inset-0 w-full h-full object-cover" />
</div>
// After (works!)
<div className="w-full h-64 overflow-hidden bg-gray-100">
<img className="w-full h-full object-cover object-center" />
</div>
Applied to:
- Classic layout
- Modern layout
- Boutique layout (h-80)
- Launch layout
2. Product Page ✅
File: customer-spa/src/pages/Product/index.tsx
Image Container:
<div className="w-full h-96 rounded-lg overflow-hidden bg-gray-100">
<img className="w-full h-full object-cover object-center" />
</div>
Query Fix: Added proper error handling and logging:
queryFn: async () => {
if (!slug) return null;
const response = await apiClient.get<ProductsResponse>(
apiClient.endpoints.shop.products,
{ slug, per_page: 1 }
);
console.log('Product API Response:', response);
if (response && response.products && response.products.length > 0) {
return response.products[0];
}
return null;
}
3. Backend API - Slug Support ✅
File: includes/Frontend/ShopController.php
Added slug parameter:
'slug' => [
'default' => '',
'sanitize_callback' => 'sanitize_text_field',
],
Added slug filtering:
// Add slug filter (for single product lookup)
if (!empty($slug)) {
$args['name'] = $slug;
}
How it works:
- WordPress
WP_Queryacceptsnameparameter namematches the post slug exactly- Returns single product when slug is provided
Why Previous Attempts Failed
Attempt 1: aspect-square class
<div className="aspect-square">
<img className="absolute inset-0" />
</div>
Problem: CSS aspect-ratio property doesn't work reliably with absolute positioning.
Attempt 2: padding-bottom technique
<div style={{ paddingBottom: '100%' }}>
<img className="absolute inset-0" />
</div>
Problem: The padding creates space, but the image positioning wasn't working in this specific component structure.
Why Fixed Height Works
<div className="h-64">
<img className="w-full h-full object-cover" />
</div>
Success:
- Container has explicit height
- Image fills container with
w-full h-full object-coverensures proper cropping- No complex positioning needed
Testing
Test Shop Page Images
- Go to
/shop - All product images should fill their containers completely
- Images should be 256px tall (or 320px for Boutique)
- No gaps or empty space
Test Product Page
- Click any product
- Product image should display (384px tall)
- Image should fill the container
- Console should show API response with product data
Check Console
Open browser console and navigate to a product page. You should see:
Product API Response: {
products: [{
id: 123,
name: "Product Name",
slug: "product-slug",
image: "https://..."
}],
total: 1
}
Summary
Root Cause: CSS aspect-ratio techniques weren't working in this setup.
Solution: Use simple fixed heights with object-cover.
Result:
- ✅ Images fill containers properly
- ✅ Product page loads images
- ✅ Backend supports slug filtering
- ✅ Simple, maintainable code
Files Modified:
customer-spa/src/components/ProductCard.tsx- Fixed all 4 layoutscustomer-spa/src/pages/Product/index.tsx- Fixed image container and queryincludes/Frontend/ShopController.php- Added slug parameter support
Lesson Learned
Sometimes the simplest solution is the best. Instead of complex CSS tricks:
- Use fixed heights when appropriate
- Let
object-coverhandle image fitting - Keep code simple and maintainable
This approach is:
- More reliable
- Easier to debug
- Better browser support
- Simpler to understand