У каждого разработчика должен быть веб-сайт портфолио, чтобы продемонстрировать свои навыки и проекты. Мы создадим веб-сайт портфолио с помощью React.js и Tailwind CSS.

Настраивать

Чтобы сначала собрать проект, нам нужно настроить проект React.js и Tailwind CSS. Вы можете легко сделать это с помощью документации Tailwind.
Следуйте этим инструкциям из документации Tailwind, чтобы настроить проект.

Настройка проекта React и Tailwind

Я подожду, пока вы настроите проект.

Вы сделали!

давайте перейдем к следующему шагу.

Компоненты

Прежде чем мы начнем, нам нужно немного узнать о структуре проекта.

Поскольку это React, мы будем разбивать веб-сайты на крошечные компоненты.

У нас будет 6 компонентов:

  1. Заголовок
  2. Герой
  3. О
  4. Проекты
  5. Блог
  6. Нижний колонтитул

Примечание: все эти компоненты будут находиться в папке компонентов в папке src. И все компоненты будут импортированы в файл 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;

№1. Заголовок

У них есть адаптивное мобильное меню с кнопкой-переключателем и настольное меню.

Мы будем использовать хук react useState для реализации эффекта переключения. А для иконок мы будем использовать библиотеку 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;

Поскольку у нас есть собственная цветовая палитра, я решил создать несколько служебных классов для цветов.

/* color */
.bg-primary {
    background: #0F172A;
}
.bg-secondery {
    background: #1E293B;
}
.bg-accent {
    background: #7477FF;
}
.text-accent {
    color: #7477FF;
}

Когда мы стилизовали мобильную навигацию с попутным ветром, она становилась очень запутанной и повторяющейся. Итак, я решил извлечь классы и поместить их в пользовательский класс с именем .mobile-nav в файле Style.css, например так:

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

Также для стилизации тегов a внутри навигации мы использовали пользовательский CSS. Иначе мы бы много повторялись.

nav li a {
    @apply px-4 py-5 text-lg;
}
nav li a:hover {
    color: #7477FF;
}

Теперь, когда мы закончили с навигацией, давайте перейдем к разделу героев.

№ 2. Герой

Герой состоит из двух разделов: информация о герое и изображение героя.

Я использовал иллюстрацию на герое-img, вы можете использовать свою картинку, если хотите.

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;

Чтобы оформить титул героя, мы использовали собственный шрифт и добавили нестандартные стили.

Примечание: вам нужно будет добавить этот шрифт в index.html вашего проекта. Это бесплатный шрифт Google.

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

№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;

Для стилизации этого раздела мы не использовали никаких других пользовательских 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",
    },
  ];

Остальная часть компонента продукта это.

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;

№ 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;

№ 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> [email protected]
        </p>
        <p className="py-2">
          <span className="font-bold">Phone:</span> +88 01624-890723
        </p>
      </div>
    </section>
  );
};
export default Contact;

#Нижний колонтитул

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;