如何使用 React 和 Tailwind CSS 构建作品集网站

2025-06-07

如何使用 React 和 Tailwind CSS 构建作品集网站

每个开发人员都必须有一个作品集网站来展示他们的技能和项目。

如果您更喜欢视频教程,可以在这里观看:

在本文中,我将向您展示如何做到这一点。
我们将使用 React.js 和 Tailwind CSS 构建作品集网站。

你可能会问,这只是一个登陆页面?
为什么不直接用原生 CSS 和 HTML 来构建呢?
我选择 React 和 Tailwind 来构建这个项目是因为我会将博客 API 集成到这个项目中。我会在以后的文章中分享。

先决条件:

为了跟上进度,您不需要成为任何方面的专家,您所需要的只是基础知识。

  1. 对 vanilla CSS 有基本的了解
  2. 对 JavaScript 有基本的了解。
  3. React 和 Tailwind 的基础知识。

现在您知道您需要什么了,让我们开始构建吧。

设置

要构建项目,首先我们需要设置一个 React.js 和 Tailwind CSS 项目。你可以使用 Tailwind 文档轻松完成此操作。
请按照Tailwind 文档中的说明设置项目。

设置 React 和 Tailwind 项目

我会等你设置好项目。

您已完成!

让我们继续下一步。

组件

在开始之前,我们需要了解一些有关项目结构的知识。

因为它是 React,所以我们会将网站分解成微小的组件。

我们将有 6 个组成部分:

  1. 标题
  2. 英雄
  3. 关于
  4. 项目
  5. 博客
  6. 页脚

注意:所有这些组件都位于src文件夹下的 components 文件夹中。所有组件都将导入到App.js文件中。

像这样:

import "./App.css";
import Header from "./components/Header";
import Hero from "./components/Hero";
import About from "./components/About";
import Projects from "./components/Projects";
import Blog from "./components/Blog";
import Contact from "./components/Contact";
import Footer from "./components/Footer";

function App() {
  return (
    <>
      <Header />
      <Hero />
      <About />
      <Projects />
      <Blog />
      <Contact />
      <Footer />
    </>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

#1. 标题

它们有一个带有切换按钮的响应式移动菜单和一个桌面菜单。

我们将使用 React 的 useState hook 来实现切换效果。对于图标,我们将使用 React Icons 库。


import React, { useState } from "react";
import { AiOutlineMenu, AiOutlineClose } from "react-icons/ai";

const Header = () => {
  const [toggle, setToggle] = useState(false);

  const handleToggle = () => setToggle(!toggle);

  return (
    <header className="flex justify-between px-5 py-2 bg-primary text-white fixed w-full z-10">
      <a href="/" className="logo text-2xl font-bold text-accent">
        Amrin
      </a>

      {/* Desktop Nav */}
      <nav className="hidden md:block">
        <ul className="flex">
          <li>
            <a href="/#about">About</a>
          </li>
          <li>
            <a href="/#projects">Projects</a>
          </li>
          <li>
            <a href="/#blog">Blog</a>
          </li>
          <li>
            <a href="/#contact">Contact</a>
          </li>
          <li>
            <a href="#resume -link" target="_blank" without rel="noreferrer">
              Resume
            </a>
          </li>
        </ul>
      </nav>

      {/* Mobile Nav */}
      <nav
        className={!toggle ? "mobile-nav left-[-100%]" : "mobile-nav left-0"}
      >
        <ul className="flex flex-col">
          <li>
            <a href="/#about">About</a>
          </li>
          <li>
            <a href="/#projects">Projects</a>
          </li>
          <li>
            <a href="/#blog">Blog</a>
          </li>
          <li>
            <a href="/#contact">Contact</a>
          </li>
          <li>
            <a href="/#resume">Resume</a>
          </li>
        </ul>
      </nav>

      {/* Toggle button */}
      <button onClick={handleToggle} className="block md:hidden">
        {!toggle ? <AiOutlineMenu size={30} /> : <AiOutlineClose size={30} />}
      </button>
    </header>
  );
};

export default Header;
Enter fullscreen mode Exit fullscreen mode

因为我们有一个自定义调色板,所以我决定为颜色创建一些实用程序类。

/* color */
.bg-primary {
    background: #0F172A;
}

.bg-secondery {
    background: #1E293B;
}

.bg-accent {
    background: #7477FF;
}

.text-accent {
    color: #7477FF;
} 
Enter fullscreen mode Exit fullscreen mode

当我们用 Tailwind 为移动端导航设计样式时,它变得非常混乱和重复。因此,我决定提取这些类,并将它们放在 Style.css 文件中名为 .mobile-nav 的自定义类中,如下所示

.mobile-nav {
    @apply block md:hidden fixed top-10 py-2 w-full h-full bg-gray-900 duration-500;
} 
Enter fullscreen mode Exit fullscreen mode

另外,为了给导航栏中的 a 标签添加样式,我们使用了一些自定义 CSS。否则我们会重复很多工作。

nav li a {
    @apply px-4 py-5 text-lg;
}

nav li a:hover {
    color: #7477FF;
}
Enter fullscreen mode Exit fullscreen mode

现在我们已经完成了导航,让我们继续进入英雄部分。

#2. 英雄

英雄由两部分组成,一部分是英雄信息,另一部分是英雄图片。

我在英雄图像上使用了插图,如果您愿意,您可以使用您的图片。

import React from "react";
import HeroImg from "../assets/hero-img.png";

import {
  AiOutlineTwitter,
  AiOutlineYoutube,
  AiOutlineFacebook,
} from "react-icons/ai";

const Hero = () => {
  return (
    <section className="bg-primary px-5 text-white py-32">
      <div className="container mx-auto grid md:grid-cols-2 items-center justify-center md:justify-between">
        <div className="hero-info pb-5 md:pb-0">
          <h1 className="text-4xl lg:text-6xl">
            Hi, <br />I am <span className="text-accent">a</span>mrin <br />
            Frontend Developer
          </h1>

          <p className="py-5">
            I am proficient in JavaScript, React.js and Tailwind CSS
          </p>

          <div className="flex py-5 ">
            <a
              href="https://twitter.com/CoderAmrin"
              className="pr-4 inline-block text-accent hover:text-white"
            >
              {" "}
              <AiOutlineTwitter size={40} />{" "}
            </a>
            <a
              href="https://www.youtube.com/@coderamrin"
              className="pr-4 inline-block text-accent hover:text-white"
            >
              {" "}
              <AiOutlineYoutube size={40} />{" "}
            </a>
            <a
              href="https://www.facebook.com/CoderAmrin/"
              className="pr-4 inline-block text-accent hover:text-white"
            >
              {" "}
              <AiOutlineFacebook size={40} />{" "}
            </a>
          </div>

          <a
            href="/#projects"
            className=" btn bg-accent  border-2 border-[#7477FF] text-white px-6 py-3 hover:bg-transparent"
          >
            See Projects
          </a>
        </div>

        <div className="hero-img">
          <img
            src={HeroImg}
            alt="coding illustration"
            className="lgw-[80%] ml-auto"
          />
        </div>
      </div>
    </section>
  );
};

export default Hero;
Enter fullscreen mode Exit fullscreen mode

为了设计英雄标题的风格,我们使用了自定义字体并添加了一些自定义样式。

注意:您需要在项目的 index.html 中添加此字体。这是一款免费的 Google 字体。

/* hero */
h1 {
    font-family: 'Pacifico', cursive;
    line-height: 1.5 !important;
}
Enter fullscreen mode Exit fullscreen mode

#3. 关于

关于部分与英雄部分一样,由两部分组成。
第一部分会介绍你的所有信息,包括你的技能以及你的工作内容。另一部分是 about-img,它是一个关于一个人编程的插图。

注意:所有图像都位于 src/assets 目录中。

import React from "react";
import AboutImg from "../assets/about-img.png";

const About = () => {
  return (
    <section className="bg-secondery text-white px-5 py-32" id="about">
      <div className="container mx-auto grid md:grid-cols-2 items-center justify-center md:justify-between">
        <div className="about-info">
          <h2 className="text-4xl font-bold mb-5 border-b-[5px] w-[180px] border-indigo-600 pb-2">
            About Me
          </h2>

          <p className="pb-5">
            Hi, My Name Is Rohima Akther everyone calls me Amrin. I am a
            Frontend Developer. I build beautifull websites with React and
            Tailwind CSS.
          </p>
          <p className="pb-5">
            I am proficient in Frontend skills like React.js, Redux, Redux Tool
            Kit, Axios, Tailwind CSS, SaSS, Css3 and many more.
          </p>

          <p>In backend I know Node.js, Express.js, MongoDB, and Mongoose</p>

          <p>
            In my spare time I create YouTube videos and write blogs on my Blog.
            Where I talk about programming theory and build various projects.
          </p>
        </div>

        <div className="about-img">
          <img
            src={AboutImg}
            alt="coding illustration"
            className="lgw-[80%] md:ml-auto"
          />
        </div>
      </div>
    </section>
  );
};

export default About;
Enter fullscreen mode Exit fullscreen mode

为了设计此部分,除了颜色类之外,我们没有使用任何其他自定义 CSS。

#4. 项目

项目部分有点复杂。首先,我们将所有项目放在一个数组中,这样就不用重复操作了。有了这个项目数组,我们现在可以轻松地映射并渲染项目项。

const projects = [
    {
      img: devlog,
      title: "devlog",
      desc: " A multi author blog. Built with Node.js, MongoDB, React, Redux and Tailwind CSS ",
      live: "https://devlogg.onrender.com/",
      code: "https://github.com/Coderamrin/devlog",
    },
    {
      img: uilogs,
      title: "uilogs",
      desc: "Free website template directory for SaaS and Degital Agency. Built with Bootstrap, JQuery and JavaScript",
      live: "https://uilogs.xyz/",
      code: "https://github.com/Coderamrin/html-templates",
    },
    {
      img: cssProjects,
      title: "css projects",
      desc: "Frontend Mentor challange directory, solved with vanilla CSS",
      live: "https://build-10-css-projects.netlify.app/",
      code: "https://github.com/Coderamrin/build-10-css-projects",
    },
    {
      img: getInspirred,
      title: "get Inspirred",
      desc: "Quote search app. Used Quotable API for the quotes and React, Redux on the frontend",
      live: "https://get-inspirred.netlify.app/",
      code: "https://github.com/Coderamrin/get-inspired",
    },
  ]; 
Enter fullscreen mode Exit fullscreen mode

产品组件的其余部分就是这样。

import React from "react";
import cssProjects from "../assets/cssprojects.png";
import devlog from "../assets/devlog.png";
import getInspirred from "../assets/get-inspirred.png";
import uilogs from "../assets/uilogs.png";

const Projects = () => {
  const projects = [...];

  return (
    <section className="bg-primary text-white px-5 py-32" id="projects">
      <div className="container mx-auto grid md:grid-cols-2 items-center md:justify-between">
        <div className="about-info mb-5">
          <h2 className="text-4xl font-bold mb-5 border-b-[5px] w-[180px] border-indigo-600 pb-2">
            Projects
          </h2>

          <p className="pb-5">
            These are some of my best projects. I have built these with React,
            MERN and vanilla CSS. Check them out.
          </p>
        </div>

        <div className="about-img"></div>
      </div>

      <div className="projects container mx-auto grid md:grid-cols-3 gap-10">
        {projects.map((project, i) => {
          return (
            <div className="relative" key={i}>
              <img src={project.img} alt={project.title} />
              <div className="flex absolute left-0 right-0 top-[13px] bottom-0 mx-auto w-[90%] h-[90%]  bg-primary  opacity-0 duration-500 justify-center flex-col hover:opacity-100 ">
                <p className="py-5 text-center font-bold px-2 text-white">
                  {project.desc}
                </p>

                <div className="mx-auto">
                  <a
                    href={project.live}
                    className="px-5 py-2 bg-blue-500 hover:bg-blue-600 mr-5 font-bold"
                  >
                    Live
                  </a>
                  <a
                    href={project.code}
                    className="px-5 py-2 bg-blue-700 hover:bg-blue-800 font-bold"
                  >
                    Code
                  </a>
                </div>
              </div>
            </div>
          );
        })}
      </div>
    </section>
  );
};

export default Projects;
Enter fullscreen mode Exit fullscreen mode

#5. 博客

现在是博客部分。它几乎和项目部分一样。

要映射并呈现项目的博客项目数组。

其余一切都与项目组件相同。

import React from "react";

const Blog = () => {
  const post = [
    {
      img: "https://res.cloudinary.com/practicaldev/image/fetch/s--AuZFJnr6--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a8okx5rxzuh5fojibsy3.png",
      title: "How to build a counter app with JavaScript",
      url: "https://dev.to/coderamrin/how-to-build-a-counter-app-with-javascript-439p",
    },
    {
      img: "https://res.cloudinary.com/practicaldev/image/fetch/s--FsJZ6lhI--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gv7y2de8kalk9l0820ag.jpg",
      title: "JavaScript Ultimate Guide 02: The DOM",
      url: "https://dev.to/coderamrin/javascript-ultimate-guide-02-the-dom-3ho9",
    },
  ];

  return (
    <section className="bg-primary text-white px-5 py-32" id="blog">
      <div className="container mx-auto grid md:grid-cols-2 items-center md:justify-between">
        <div className="about-info mb-5">
          <h2 className="text-4xl font-bold mb-5 border-b-[5px] w-[100px] border-indigo-600 pb-2">
            Blogs
          </h2>

          <p className="pb-5">Some of my best blogs.</p>
        </div>

        <div></div>
      </div>

      <div className="projects container mx-auto grid md:grid-cols-2 gap-10">
        {post.map((item) => {
          return (
            <div>
              <img src={item.img} alt={item.title} />
              <h3 className="py-5 text-2xl">{item.title}</h3>
              <a
                href={item.url}
                className=" btn bg-accent  border-2 border-[#7477FF] text-white px-6 py-3 hover:bg-transparent"
              >
                Read More
              </a>
            </div>
          );
        })}
      </div>
    </section>
  );
};

export default Blog; 
Enter fullscreen mode Exit fullscreen mode

#6. 联系方式和页脚

最后是联系部分和页脚部分。

这些部分只是 div 中心的一些文本。没什么特别的设计。

#接触

import React from "react";

const Contact = () => {
  return (
    <section className="bg-secondery px-5 py-32" id="contact">
      <div className="text-center md:w-[60%] mx-auto text-white">
        <h2 className="text-4xl font-bold mb-5 border-b-[5px] w-[200px] mx-auto border-indigo-600 pb-2">
          Contact Me
        </h2>
        <p>
          I am currently open for a fulltime Frontend Developer role. If you
          want to discuss about that feel free to email me or call me.
        </p>

        <p className="py-2">
          <span className="font-bold">Email:</span> coderamrin@gmail.com
        </p>
        <p className="py-2">
          <span className="font-bold">Phone:</span> +88 01624-890723
        </p>
      </div>
    </section>
  );
};

export default Contact;
Enter fullscreen mode Exit fullscreen mode

#页脚

import React from "react";

const Footer = () => {
  return <div className="py-4 text-center bg-primary text-white "> &copy; 2023 coderamrin all right reserved</div>;
};

export default Footer;
Enter fullscreen mode Exit fullscreen mode

资源

直播: https://amrin.onrender.com/
源代码: https://github.com/Coderamrin/portfolio

结论

现在您有了一个作品集。您可以部署它并展示您的项目。

如果您愿意,您可以将博客添加到您的作品集并展示您的技能。

我将在这个作品集上添加 dev api,如果您想看到同样的事情,请关注我,以便在我发布文章时收到通知。

如果您想与我联系,您可以在TwitterYouTube上找到我。

感谢您阅读到最后。

我们下篇文章再见。

文章来源:https://dev.to/coderamrin/how-to-build-a-portfolio-website-with-react-tailwind-css-fni
PREV
使用 HTML、CSS 和 Javascript 的响应式导航栏
NEXT
极简 Python:重温 Lambda 表达式、装饰器和其他魔法函数 什么是函数式编程? 递归 嵌套函数 闭包 Lambda 表达式 装饰器 回顾