feat: optimize product images to e-commerce standard (600x600 → 300px display)
INDUSTRY STANDARD IMPLEMENTATION: - Change placeholder images from 300x200 (3:2) to 600x600 (1:1 square) - Set max-height to 300px with aspect-ratio 1:1 for consistent display - Follow e-commerce best practices (Amazon, Shopify, Mercado Libre) TEMPLATE CHANGES: - catalog.vue: Update placeholder URL to 600x600 square images - Card.vue: Add aspect-ratio="1" for perfect square display - Card.vue: Increase max-height from 140px to 300px - Restore padding: pa-2 → pa-3 (8px → 12px) - Restore title size: text-subtitle-2 → text-subtitle-1 - Restore margins: mb-1 → mb-2 - Restore chip size: x-small → small - Restore footer padding: pa-2 → pa-2 pb-3 CSS CHANGES: - Remove fixed height from .product-image-container (use 100% for flexibility) - Product name: 0.85rem → 0.95rem, min-height 2rem → 2.5rem - Price label: 0.6rem → 0.65rem - Price value: 0.9rem → 1.1rem - Price chip: height 22px → 26px, font 0.75rem → 0.9rem - Quantity input: 55px → 65px, font 0.85rem → 0.95rem - Section gaps: 2px → 4px, row gaps: 1px → 2px RESPONSIVE STRATEGY (optimized for 300px max): - Mobile XS (<375px): Natural scaling, compact layout - Mobile (375-559px): Natural scaling, readable text - Tablet (560-959px): Enhanced padding and fonts - Desktop (≥960px): Full 300px display with optimal spacing - Desktop L/XL: Maintain 300px with enhanced typography RESULT: - Square images (1:1) matching industry standard - 600x600 source allows retina displays and zoom - 300px display on desktop (sweet spot for catalogs) - Responsive scaling maintains aspect ratio - Professional e-commerce appearance
This commit is contained in:
@@ -2,50 +2,58 @@
|
||||
<v-card class="product-card" elevation="2" rounded="lg">
|
||||
<!-- Imagen del Producto -->
|
||||
<div class="product-image-container">
|
||||
<v-img
|
||||
:src="product.img"
|
||||
<v-img
|
||||
:src="product.img"
|
||||
:alt="product.name"
|
||||
class="product-img"
|
||||
class="product-img"
|
||||
cover
|
||||
max-height="140"
|
||||
max-height="300"
|
||||
aspect-ratio="1"
|
||||
>
|
||||
<template v-slot:placeholder>
|
||||
<div class="d-flex align-center justify-center fill-height">
|
||||
<v-progress-circular indeterminate color="primary" size="32"></v-progress-circular>
|
||||
<v-progress-circular
|
||||
indeterminate
|
||||
color="primary"
|
||||
size="32"
|
||||
></v-progress-circular>
|
||||
</div>
|
||||
</template>
|
||||
</v-img>
|
||||
</div>
|
||||
|
||||
<!-- Contenido de la Tarjeta -->
|
||||
<v-card-text class="product-content pa-2 text-center">
|
||||
<v-card-text class="product-content pa-3 text-center">
|
||||
<!-- Título del Producto -->
|
||||
<v-tooltip location="top" :text="product.name">
|
||||
<template v-slot:activator="{ props }">
|
||||
<h3 class="product-name text-subtitle-2 font-weight-medium mb-1" v-bind="props">
|
||||
<h3
|
||||
class="product-name text-subtitle-1 font-weight-medium mb-2"
|
||||
v-bind="props"
|
||||
>
|
||||
{{ product.name }}
|
||||
</h3>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
|
||||
<!-- Sección de Precios -->
|
||||
<div class="prices-section mb-1">
|
||||
<div class="prices-section mb-2">
|
||||
<!-- Precio Unitario -->
|
||||
<div class="price-row">
|
||||
<div class="price-row mb-1">
|
||||
<span class="price-label text-caption">Precio unitario</span>
|
||||
<div class="price-value text-body-2 font-weight-bold text-primary">
|
||||
<div class="price-value text-body-1 font-weight-bold text-primary">
|
||||
{{ currency(product.price) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Precio Total -->
|
||||
<div class="price-row">
|
||||
<span class="price-label text-caption">Precio total</span>
|
||||
<v-chip
|
||||
color="success"
|
||||
variant="flat"
|
||||
size="x-small"
|
||||
class="price-total-chip font-weight-bold"
|
||||
<v-chip
|
||||
color="success"
|
||||
variant="flat"
|
||||
size="small"
|
||||
class="price-total-chip font-weight-bold mt-1"
|
||||
>
|
||||
{{ currency(product.price * product.quantity) }}
|
||||
</v-chip>
|
||||
@@ -54,11 +62,11 @@
|
||||
</v-card-text>
|
||||
|
||||
<!-- Footer con Controles de Cantidad -->
|
||||
<v-card-actions class="product-actions pa-2 justify-center">
|
||||
<v-card-actions class="product-actions pa-2 pb-3 justify-center">
|
||||
<div class="quantity-controls">
|
||||
<v-btn
|
||||
<v-btn
|
||||
icon
|
||||
size="small"
|
||||
size="small"
|
||||
variant="tonal"
|
||||
color="error"
|
||||
class="qty-btn"
|
||||
@@ -67,7 +75,7 @@
|
||||
>
|
||||
<v-icon size="20">mdi-minus</v-icon>
|
||||
</v-btn>
|
||||
|
||||
|
||||
<v-text-field
|
||||
v-model.number="product.quantity"
|
||||
type="number"
|
||||
@@ -81,10 +89,10 @@
|
||||
aria-label="Cantidad"
|
||||
@input="handleQuantityChange"
|
||||
/>
|
||||
|
||||
<v-btn
|
||||
|
||||
<v-btn
|
||||
icon
|
||||
size="small"
|
||||
size="small"
|
||||
variant="tonal"
|
||||
color="success"
|
||||
class="qty-btn"
|
||||
@@ -162,7 +170,7 @@ export default {
|
||||
.product-image-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 140px;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(135deg, #fafafa 0%, #ffffff 100%);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
@@ -190,16 +198,16 @@ export default {
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-size: 0.85rem;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 500;
|
||||
color: #1a1a1a;
|
||||
line-height: 1.2;
|
||||
line-height: 1.3;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
min-height: 2rem;
|
||||
min-height: 2.5rem;
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
|
||||
@@ -211,20 +219,20 @@ export default {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.price-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 1px;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.price-label {
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.8px;
|
||||
font-size: 0.6rem;
|
||||
font-size: 0.65rem;
|
||||
color: #9e9e9e;
|
||||
font-weight: 500;
|
||||
}
|
||||
@@ -232,14 +240,14 @@ export default {
|
||||
.price-value {
|
||||
color: #1565c0;
|
||||
letter-spacing: 0.02em;
|
||||
font-size: 0.9rem;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.price-total-chip {
|
||||
letter-spacing: 0.03em;
|
||||
font-size: 0.75rem;
|
||||
padding: 0 10px;
|
||||
height: 22px;
|
||||
font-size: 0.9rem;
|
||||
padding: 0 12px;
|
||||
height: 26px;
|
||||
box-shadow: 0 2px 8px rgba(76, 175, 80, 0.25);
|
||||
}
|
||||
|
||||
@@ -259,8 +267,8 @@ export default {
|
||||
}
|
||||
|
||||
.quantity-input {
|
||||
max-width: 55px;
|
||||
min-width: 55px;
|
||||
max-width: 65px;
|
||||
min-width: 65px;
|
||||
}
|
||||
|
||||
.quantity-input :deep(.v-field) {
|
||||
@@ -272,10 +280,10 @@ export default {
|
||||
.quantity-input :deep(.v-field__input) {
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
font-size: 0.85rem;
|
||||
font-size: 0.95rem;
|
||||
color: #1a1a1a;
|
||||
padding: 2px 0;
|
||||
min-height: 28px;
|
||||
padding: 4px 0;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.quantity-input :deep(.v-field__field) {
|
||||
@@ -301,23 +309,153 @@ export default {
|
||||
|
||||
/* Móvil pequeño (< 375px) */
|
||||
@media (max-width: 374px) {
|
||||
.product-image-container {
|
||||
height: 130px;
|
||||
.product-content {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-size: 0.9rem;
|
||||
min-height: 2.4rem;
|
||||
}
|
||||
|
||||
.price-value {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.quantity-input {
|
||||
max-width: 60px;
|
||||
min-width: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Móvil estándar (375px - 559px) */
|
||||
@media (min-width: 375px) and (max-width: 559px) {
|
||||
.product-name {
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.price-value {
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tablet (560px - 959px) */
|
||||
@media (min-width: 560px) and (max-width: 959px) {
|
||||
.product-content {
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-size: 1rem;
|
||||
min-height: 2.6rem;
|
||||
}
|
||||
|
||||
.price-label {
|
||||
font-size: 0.68rem;
|
||||
}
|
||||
|
||||
.price-value {
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
.price-total-chip {
|
||||
font-size: 0.95rem;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.quantity-input {
|
||||
max-width: 70px;
|
||||
min-width: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktop (≥ 960px) */
|
||||
@media (min-width: 960px) {
|
||||
.product-content {
|
||||
padding: 16px 14px;
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-size: 1.05rem;
|
||||
min-height: 2.7rem;
|
||||
}
|
||||
|
||||
.price-label {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.price-value {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.price-total-chip {
|
||||
font-size: 1rem;
|
||||
height: 30px;
|
||||
padding: 0 14px;
|
||||
}
|
||||
|
||||
.product-actions {
|
||||
padding: 8px;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
.quantity-input {
|
||||
max-width: 70px;
|
||||
min-width: 70px;
|
||||
}
|
||||
|
||||
.qty-btn {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktop Large (≥ 1280px) */
|
||||
@media (min-width: 1280px) {
|
||||
.product-content {
|
||||
padding: 18px 16px;
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-size: 1.1rem;
|
||||
min-height: 2.8rem;
|
||||
}
|
||||
|
||||
.price-value {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.price-total-chip {
|
||||
font-size: 1.05rem;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktop Extra Large (≥ 1920px) */
|
||||
@media (min-width: 1920px) {
|
||||
.product-name {
|
||||
font-size: 1.15rem;
|
||||
min-height: 3rem;
|
||||
}
|
||||
|
||||
.price-value {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
}
|
||||
|
||||
.product-content {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
|
||||
.product-name {
|
||||
font-size: 0.8rem;
|
||||
min-height: 1.9rem;
|
||||
}
|
||||
|
||||
|
||||
.price-value {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
|
||||
.quantity-input {
|
||||
max-width: 50px;
|
||||
min-width: 50px;
|
||||
@@ -329,11 +467,11 @@ export default {
|
||||
.product-image-container {
|
||||
height: 140px;
|
||||
}
|
||||
|
||||
|
||||
.product-name {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
|
||||
.price-value {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
@@ -344,29 +482,29 @@ export default {
|
||||
.product-image-container {
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
|
||||
.product-content {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
|
||||
.product-name {
|
||||
font-size: 0.9rem;
|
||||
min-height: 2.1rem;
|
||||
}
|
||||
|
||||
|
||||
.price-label {
|
||||
font-size: 0.62rem;
|
||||
}
|
||||
|
||||
|
||||
.price-value {
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
|
||||
.price-total-chip {
|
||||
font-size: 0.8rem;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
|
||||
.quantity-input {
|
||||
max-width: 58px;
|
||||
min-width: 58px;
|
||||
@@ -378,40 +516,40 @@ export default {
|
||||
.product-image-container {
|
||||
height: 160px;
|
||||
}
|
||||
|
||||
|
||||
.product-content {
|
||||
padding: 12px 10px;
|
||||
}
|
||||
|
||||
|
||||
.product-name {
|
||||
font-size: 0.95rem;
|
||||
min-height: 2.2rem;
|
||||
}
|
||||
|
||||
|
||||
.price-label {
|
||||
font-size: 0.63rem;
|
||||
}
|
||||
|
||||
|
||||
.price-value {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
|
||||
.price-total-chip {
|
||||
font-size: 0.85rem;
|
||||
height: 25px;
|
||||
padding: 0 11px;
|
||||
}
|
||||
|
||||
|
||||
.product-actions {
|
||||
padding: 6px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
|
||||
.quantity-input {
|
||||
max-width: 58px;
|
||||
min-width: 58px;
|
||||
}
|
||||
|
||||
|
||||
.qty-btn {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
@@ -423,20 +561,20 @@ export default {
|
||||
.product-image-container {
|
||||
height: 170px;
|
||||
}
|
||||
|
||||
|
||||
.product-content {
|
||||
padding: 14px 12px;
|
||||
}
|
||||
|
||||
|
||||
.product-name {
|
||||
font-size: 1rem;
|
||||
font-size: 2rem;
|
||||
min-height: 2.4rem;
|
||||
}
|
||||
|
||||
|
||||
.price-value {
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
||||
|
||||
.price-total-chip {
|
||||
font-size: 0.9rem;
|
||||
height: 26px;
|
||||
@@ -448,12 +586,12 @@ export default {
|
||||
.product-image-container {
|
||||
height: 180px;
|
||||
}
|
||||
|
||||
|
||||
.product-name {
|
||||
font-size: 1.05rem;
|
||||
min-height: 2.5rem;
|
||||
}
|
||||
|
||||
|
||||
.price-value {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ export default {
|
||||
quantity: 0,
|
||||
img:
|
||||
product.img ||
|
||||
`https://picsum.photos/300/200?random=${product.id}`,
|
||||
`https://picsum.photos/600/600?random=${product.id}`,
|
||||
}));
|
||||
})
|
||||
.catch((error) => {
|
||||
|
||||
Reference in New Issue
Block a user