Cómo crear cards modernas con React y Tailwind

Cómo crear tarjetas modernas con React y Tailwind portada

Hoy te voy a enseñar cómo crear unos cards muy vistosos con React y Tailwind. Uno de mis componentes favoritos son sin duda las cards y las razones son muy sencillas, pueden tener muchos usos, le dan un dinamismo bastante bonito a la web y son una buena manera de separar elementos que, de otra manera, estarían condenados a ir en una lista o en una tabla.

Cómo crear cards modernas con React y Tailwind

Antes de comenzar

Del mismo modo que puede utilizarse para contenidos informativos (como breves descripciones), también puede utilizarse para centrar la atención del usuario momentáneamente (como una publicación en las redes sociales) o para que el usuario realice una acción.

A la hora de diseñar una tarjeta debemos prestar atención a algunos aspectos:

  • Todo el contenido debe estar contenido en un solo elemento;
  • No es necesario que haya otros elementos auxiliares para dar algún contexto al contenido de la tarjeta;

A partir de estos pequeños puntos sólo hay que prestar atención a algunos aspectos en cuanto a la anatomía del elemento.

Obviamente, muchos de los elementos acaban siendo opcionales y por esa misma razón hoy sólo me voy a centrar en estos:

  • Contenedor – contiene todos los elementos de la tarjeta y generalmente estos mismos elementos dictan el tamaño de la tarjeta, sin embargo, a mí me gusta hacer lo contrario, que es definir el espacio máximo que pueden ocupar;
  • Miniatura – es un elemento visual importante, sin embargo este artículo será por razones de estilo;
  • Botones – normalmente los botones se agrupan en un solo espacio y cada botón corresponde a una acción que el usuario puede realizar;

Y uno de los aspectos que me parece interesante es que es un componente que generalmente tiene un gran comportamiento en cuanto a la capacidad de respuesta.

De todos modos, estos son sólo algunos aspectos que tengo en cuenta cuando trabajo con elementos de la interfaz, por lo que te recomiendo que leas esta página de Material Design en la que se explica con detalle qué tipo de comportamiento debe tener este componente.

Así se ve el ejemplo

En el ejemplo de hoy haremos una tarjeta sencilla, pero en mi opinión tiene un diseño muy diferente al de muchas librerías y frameworks. Un comportamiento que recomiendo adoptar es dedicar unos minutos diarios a ver diseños que te parezcan interesantes y traté de copiarlos. Espero que al final del artículo de hoy tengas un resultado similar:

Cómo crear cards modernas con React y Tailwind

Comenzamos a codificar

El framework que vamos a utilizar hoy es Tailwind CSS y junto con este framework vamos a utilizar otras herramientas como classnames y react-icons.

npm install classnames react-icons

Después crearemos un archivo con el contenido de las cards.

export default [
  {
    title: "Ascenso del Pícaro",
    likes: Math.floor(Math.random() * (50 - 0) + 0),
    image: "https://bit.ly/3BQdTqk",
  },
  {
    title: "El fin de la locura",
    likes: Math.floor(Math.random() * (50 - 0) + 0),
    image: "https://bit.ly/3CQFPvv",
  },
  {
    title: "Un poder mayor",
    likes: Math.floor(Math.random() * (50 - 0) + 0),
    image: "https://bit.ly/3ERuyMd",
  },
  {
    title: "2099: Oasis",
    likes: Math.floor(Math.random() * (50 - 0) + 0),
    image: "https://bit.ly/3CQKSwb",
  },
];

Ahora podemos empezar a trabajar en nuestra tarjeta, pero primero vamos a crear los estilos para nuestro componente:

.wrapper {
  @apply bg-white hover:bg-gray-800 shadow-xl hover:shadow-none cursor-pointer w-80 rounded-3xl flex flex-col items-center justify-center;
}

.wrapperAnime {
  @apply transition-all duration-500 ease-in-out;
}

.header {
  @apply relative mt-2 mx-2;
}

.imageWrapper {
  @apply h-56 rounded-2xl overflow-hidden;
}

.image {
  @apply object-cover w-full h-full;
}

.textWrapper {
  @apply pt-10 pb-6 w-full px-4;
}

.text {
  @apply font-medium leading-none text-base tracking-wider text-gray-400;
}

.badgeWrapper {
  @apply absolute bottom-0 left-0 -mb-4 ml-3 flex flex-row;
}

.dangerBadge {
  @apply h-10 w-10 flex items-center justify-center text-xl bg-white hover:bg-red-500 text-red-500 hover:text-white rounded-2xl shadow-xl;
}

.primaryBadge {
  @apply h-10 w-16 ml-2 bg-white hover:bg-blue-600 flex items-center justify-center font-medium text-blue-600 hover:text-white rounded-2xl shadow-xl;
}

.counter {
  @apply text-gray-800 ml-2;
}

.badgeAnime {
  @apply transform-gpu translate-y-0 hover:-translate-y-1 transition-all duration-300 ease-in-out;
}

Ahora podemos empezar a trabajar en el jsx de nuestro componente. Nuestro componente recibirá cuatro props, que serán el título, el número de likes, el orden del elemento del array y la imagen.

Después podemos importar nuestros iconos y podemos empezar a aplicar los estilos de nuestro componente:

import React from "react";
import classNames from "classnames";
import { AiFillHeart } from "react-icons/ai";
import { BsChatSquareFill } from "react-icons/bs";

import styles from "./Card.module.css";

const Card = ({ title, likes, order, image }) => {
  return (
    <div className={classNames([styles.wrapper, styles.wrapperAnime])}>
      <div className={styles.header}>
        <div className={styles.imageWrapper}>
          <img src={image} className={styles.image} alt="" />
        </div>
        <div className={styles.badgeWrapper}>
          <div
            className={classNames([styles.dangerBadge, styles.badgeAnime])}
          >
            <AiFillHeart />
          </div>
          <div
            className={classNames([
              styles.primaryBadge,
              styles.badgeAnime,
              "group",
            ])}
          >
            <BsChatSquareFill />
            <span
              className={classNames([styles.counter, "group-hover:text-white"])}
            >
              {likes}
            </span>
          </div>
        </div>
      </div>
      <div className={styles.textWrapper}>
        <h1 className={styles.text}>{`${order}. ${title}`}</h1>
      </div>
    </div>
  );
};

export default Card;

Por último, tenemos que ir a nuestro archivo de entrada (que en este caso es App.jsx) y tendremos los siguientes estilos:

.section {
  @apply bg-gray-100 h-full md:h-screen w-full;
}

.container {
  @apply container mx-auto px-0 md:px-4 py-4;
}

.layout {
  @apply grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 justify-items-center gap-4;
}

Ahora, en nuestro App.jsx vamos a importar nuestros datos de los puestos y nuestro componente Card que hemos creado, y luego vamos a hacer un bucle y pasar los props necesarios.

import React from "react";

import styles from "./App.module.css";
import Card from "./components/Card";
import posts from "./data/posts";

const App = () => {
  return (
    <main className={styles.section}>
      <section className={styles.container}>
        <div className={styles.layout}>
          {posts.map((element, index) => (
            <Card
              key={index}
              title={element.title}
              likes={element.likes}
              order={index + 1}
              image={element.image}
            />
          ))}
        </div>
      </section>
    </main>
  );
};

export default App;

Conclusión

Como siempre, espero que te haya resultado interesante. Si has detectado algún error en este artículo, por favor, menciónalo en los comentarios. 🧑🏻💻