如何使用 React 和 Tailwind 创建现代卡片 让我们来编码

2025-05-24

如何使用 React 和 Tailwind 创建现代卡片

让我们开始编码

概述

我最喜欢的组件之一无疑是卡片,原因很简单,它们有很多用途。

它既可以用于信息内容(例如简短描述),也可以用于暂时集中用户的注意力(例如社交媒体上的帖子)或让用户采取行动。

在设计卡片时我们需要注意以下几个方面:

  • 所有内容必须包含在单个元素中;
  • 你不需要其他辅助元素来为卡片的内容提供一些背景;

从这些小点来看,我们只需要关注元素解剖学的几个方面。

显然,许多元素最终都是可选的,出于同样的原因,今天我只会关注这些:

  • 容器 - 包含卡片的所有元素,通常这些相同的元素决定了卡片的大小,但是,我喜欢做相反的事情,即定义它们可以占用的最大空间;
  • 缩略图——这是一个重要的视觉元素,但本文出于风格原因不使用缩略图;
  • 按钮——通常按钮集中在一个空间内,每个按钮对应用户可以采取的一个操作;

我发现有趣的一个方面是,它是一个在响应性方面通常具有出色行为的组件。

无论如何,这些只是我在处理界面元素时考虑的几个方面,所以我建议阅读这个Material Design页面,其中详细解释了这个组件应该具有什么样的行为。

今天的例子

在今天的例子中,我们将制作一张简单的卡片,但在我看来,与许多库和框架相比,它的设计非常不同。我建议大家每天花几分钟时间看看自己感兴趣的设计,我尝试过模仿它们。希望在今天的文章结束时,你能有类似的收获:

卡最终结果

让我们开始编码

我们今天要使用的框架是 Tailwind CSS,除了这个框架之外,我们还将使用其他工具,例如 classnames 和 react-icons。

npm install classnames react-icons
Enter fullscreen mode Exit fullscreen mode

之后我们将创建一个包含卡片内容的文件。

// @src/data/posts.js

export default [
  {
    title: "Rogue's Rise",
    likes: Math.floor(Math.random() * (50 - 0) + 0),
    image: "https://bit.ly/3BQdTqk",
  },
  {
    title: "Fool's End",
    likes: Math.floor(Math.random() * (50 - 0) + 0),
    image: "https://bit.ly/3CQFPvv",
  },
  {
    title: "A Greater Power",
    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",
  },
];
Enter fullscreen mode Exit fullscreen mode

现在我们可以开始制作卡片了,但首先让我们为组件创建样式:

/* @src/components/Card.module.css */

.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;
}
Enter fullscreen mode Exit fullscreen mode

现在我们可以开始编写组件的 jsx 代码了。我们的组件将接收四个 props,分别是标题、点赞数、数组元素的顺序和图片。

之后,我们可以导入图标并开始应用组件的样式:

// @src/components/Card.jsx

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;
Enter fullscreen mode Exit fullscreen mode

最后但并非最不重要的一点是,我们必须转到我们的入口文件(在本例中为 App.jsx),我们将拥有以下样式:

/* @src/App.module.css */

.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;
}
Enter fullscreen mode Exit fullscreen mode

现在在我们的 App.jsx 中,我们将从我们创建的帖子和 Card 组件中导入数据,然后循环并传入必要的 props。

// @src/App.jsx

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;
Enter fullscreen mode Exit fullscreen mode

结论

一如既往,希望你觉得这篇文章有趣。如果你发现本文有任何错误,请在评论区指出。🧑🏻‍💻

祝你度过美好的一天!✌️

文章来源:https://dev.to/franciscomendes10866/how-to-create-modern-cards-using-react-and-tailwind-2ded
PREV
如何在 React 中将组件作为 Props 传递?让我们来编码
NEXT
如何使用 React 和 Tailwind 创建通知/Toast 让我们来编码