DEV Community

Cover image for Diseño e Implementación de Cards en Desarrollo Web Moderno
Joaquín Gutiérrez
Joaquín Gutiérrez

Posted on

Diseño e Implementación de Cards en Desarrollo Web Moderno

Las cards (tarjetas) son uno de los componentes más versátiles en el diseño web moderno. Se utilizan para presentar información de manera concisa y visualmente atractiva, desde productos en tiendas online hasta artículos en blogs. En esta guía, exploraremos diferentes implementaciones y mejores prácticas.

Anatomía de una Card

Una card típica consta de varios elementos:

<div class="card">
  <!-- Imagen -->
  <img src="imagen.jpg" alt="Descripción" class="card-image">

  <!-- Contenido -->
  <div class="card-content">
    <h2 class="card-title">Título de la Card</h2>
    <p class="card-description">Descripción o contenido principal</p>

    <!-- Pie de Card -->
    <div class="card-footer">
      <button class="card-button">Acción Principal</button>
      <span class="card-meta">Info adicional</span>
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Implementaciones

1. Card Básica con CSS

.card {
  width: 300px;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  transition: transform 0.2s ease;
}

.card:hover {
  transform: translateY(-4px);
}

.card-image {
  width: 100%;
  height: 200px;
  object-fit: cover;
}

.card-content {
  padding: 16px;
}

.card-title {
  margin: 0 0 8px;
  font-size: 1.25rem;
}

.card-description {
  color: #666;
  line-height: 1.5;
}

.card-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 16px;
  margin-top: 16px;
  border-top: 1px solid #eee;
}
Enter fullscreen mode Exit fullscreen mode

2. Card con Tailwind CSS

<div class="max-w-sm rounded overflow-hidden shadow-lg hover:-translate-y-1 transition-transform">
  <img class="w-full h-48 object-cover" src="imagen.jpg" alt="Descripción">
  <div class="px-6 py-4">
    <h2 class="font-bold text-xl mb-2">Título de la Card</h2>
    <p class="text-gray-700 text-base">
      Descripción o contenido principal
    </p>
  </div>
  <div class="px-6 py-4 border-t border-gray-200">
    <button class="bg-blue-500 text-white px-4 py-2 rounded">
      Acción
    </button>
    <span class="text-gray-500 text-sm">Meta info</span>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

3. Componente React con TypeScript

interface CardProps {
  image: string;
  title: string;
  description: string;
  action?: () => void;
  meta?: string;
}

const Card: React.FC<CardProps> = ({
  image,
  title,
  description,
  action,
  meta
}) => {
  return (
    <div className="card">
      <img
        src={image}
        alt={title}
        className="card-image"
        loading="lazy"
      />
      <div className="card-content">
        <h2 className="card-title">{title}</h2>
        <p className="card-description">{description}</p>

        <div className="card-footer">
          {action && (
            <button
              onClick={action}
              className="card-button"
            >
              Ver más
            </button>
          )}
          {meta && <span className="card-meta">{meta}</span>}
        </div>
      </div>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

4. Componente Vue 3

<template>
  <div class="card">
    <img :src="image" :alt="title" class="card-image">
    <div class="card-content">
      <h2 class="card-title">{{ title }}</h2>
      <p class="card-description">{{ description }}</p>

      <div class="card-footer">
        <button
          v-if="action"
          @click="action"
          class="card-button"
        >
          Ver más
        </button>
        <span v-if="meta" class="card-meta">{{ meta }}</span>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
defineProps<{
  image: string;
  title: string;
  description: string;
  action?: () => void;
  meta?: string;
}>();
</script>
Enter fullscreen mode Exit fullscreen mode

Patrones de Diseño

1. Card Grid Responsiva

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 24px;
  padding: 24px;
}
Enter fullscreen mode Exit fullscreen mode

2. Cards con Aspect Ratio

.card-image-container {
  position: relative;
  padding-top: 56.25%; /* 16:9 Aspect Ratio */
}

.card-image {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
Enter fullscreen mode Exit fullscreen mode

3. Skeleton Loading

.card-skeleton {
  animation: pulse 1.5s infinite;
}

@keyframes pulse {
  0% { opacity: 0.6; }
  50% { opacity: 1; }
  100% { opacity: 0.6; }
}
Enter fullscreen mode Exit fullscreen mode

Accesibilidad

<div 
  class="card" 
  role="article"
  tabindex="0"
>
  <img 
    src="imagen.jpg" 
    alt="Descripción detallada"
    aria-describedby="card-desc"
  >
  <div class="card-content">
    <h2 id="card-title">Título</h2>
    <p id="card-desc">Descripción</p>
    <button 
      class="card-button"
      aria-labelledby="card-title"
    >
      Ver más
    </button>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Mejores Prácticas

  1. Optimización de Imágenes
import Image from 'next/image';

<Image
  src={imageUrl}
  alt={title}
  width={300}
  height={200}
  placeholder="blur"
  blurDataURL={thumbnailUrl}
/>
Enter fullscreen mode Exit fullscreen mode
  1. Manejo de Errores de Imagen
const handleImageError = (e: React.SyntheticEvent<HTMLImageElement>) => {
  e.currentTarget.src = '/placeholder.jpg';
};

<img
  src={imageUrl}
  onError={handleImageError}
  alt={title}
/>
Enter fullscreen mode Exit fullscreen mode
  1. Truncado de Texto
.card-title {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
Enter fullscreen mode Exit fullscreen mode

Animaciones

/* Hover Effects */
.card {
  transition: all 0.3s ease;
}

.card:hover {
  transform: translateY(-4px);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
}

/* Click Effect */
.card:active {
  transform: translateY(-2px);
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
}
Enter fullscreen mode Exit fullscreen mode

Consideraciones de Rendimiento

  1. Lazy Loading
<img 
  loading="lazy"
  src="imagen.jpg"
  alt="Descripción"
>
Enter fullscreen mode Exit fullscreen mode
  1. Intersection Observer
useEffect(() => {
  const observer = new IntersectionObserver(
    (entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          // Cargar contenido
        }
      });
    },
    { threshold: 0.1 }
  );

  observer.observe(cardRef.current);
  return () => observer.disconnect();
}, []);
Enter fullscreen mode Exit fullscreen mode

Conclusión

Las cards son componentes fundamentales en el diseño web moderno. Una buena implementación debe considerar:

  • Diseño responsivo
  • Accesibilidad
  • Rendimiento
  • Experiencia de usuario
  • Mantenibilidad del código

Recursos Adicionales

Speedy emails, satisfied customers

Postmark Image

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay