Project: Build a Personal Portfolio Website using Flexbox

Step-by-step project guide. Learn how to build a responsive personal developer portfolio website using HTML and CSS Flexbox.

Introduction

The best way to solidify your CSS knowledge is to build projects. In this first capstone project, you will build a Personal Portfolio Website from scratch.

A portfolio is the most critical asset for a frontend developer. It showcases your skills, hosts links to your work, and serves as your visual resume for placements. In this project, we will use semantic HTML5 structure, clean custom variables, and Flexbox for alignments, creating a responsive, premium layout that looks polished on both mobile and desktop.


What You Will Learn

  • Building a semantic HTML5 page structure.
  • Creating a responsive navbar that collapses on mobile.
  • Centering and aligning text blocks inside a hero banner.
  • Aligning a grid of project cards using Flexbox wrapping.
  • Customizing form input styles for a contact form.

Prerequisites


Project Specifications

Color Theme:

  • Background: Dark slate (#0f172a)
  • Card backgrounds: Slate (#1e293b)
  • Primary Accent: Indigo (#6366f1)
  • Text: White (#ffffff) and gray (#94a3b8)

Typography:

  • Headings: Sans-serif (Inter/Outfit)
  • Body: Sans-serif

Step 1: The HTML5 Document Structure

Create an index.html file and lay out the semantic blocks:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Developer Portfolio</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>

  <!-- Navigation Bar -->
  <header class="navbar">
    <div class="logo">DevPortfolio</div>
    <nav class="nav-links">
      <a href="#about">About</a>
      <a href="#projects">Projects</a>
      <a href="#contact">Contact</a>
    </nav>
  </header>

  <!-- Hero Section -->
  <section id="about" class="hero">
    <div class="hero-content">
      <h1>Hi, I'm <span class="accent">Alex</span></h1>
      <p>Frontend Engineer specializing in premium web experiences.</p>
      <a href="#contact" class="btn-primary">Get In Touch</a>
    </div>
  </section>

  <!-- Projects Section -->
  <section id="projects" class="projects">
    <h2>My Projects</h2>
    <div class="projects-grid">
      
      <!-- Card 1 -->
      <div class="project-card">
        <h3>E-Commerce Interface</h3>
        <p>A responsive online store interface built with HTML5 and Flexbox layout rules.</p>
        <a href="#" class="project-link">View Project →</a>
      </div>

      <!-- Card 2 -->
      <div class="project-card">
        <h3>Dashboard Console</h3>
        <p>A dark-mode analytics console showcasing visual tables and custom scrollbars.</p>
        <a href="#" class="project-link">View Project →</a>
      </div>

    </div>
  </section>

  <!-- Contact Section -->
  <section id="contact" class="contact">
    <h2>Contact Me</h2>
    <form class="contact-form">
      <input type="text" placeholder="Name" required>
      <input type="email" placeholder="Email" required>
      <textarea placeholder="Message" rows="5" required></textarea>
      <button type="submit" class="btn-primary">Send Message</button>
    </form>
  </section>

</body>
</html>

Step 2: The CSS Stylesheet (style.css)

Create a style.css file. We will define custom variables and use Flexbox to lay out the sections:

/* ==========================================================================
   Base Resets & CSS Variables
   ========================================================================== */
:root {
  --bg-dark: #0f172a;
  --bg-card: #1e293b;
  --color-primary: #6366f1;
  --color-primary-hover: #4f46e5;
  --text-white: #ffffff;
  --text-gray: #94a3b8;
  --font-sans: 'Inter', system-ui, -apple-system, sans-serif;
}

*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  scroll-behavior: smooth;
}

body {
  background-color: var(--bg-dark);
  color: var(--text-white);
  font-family: var(--font-sans);
  line-height: 1.6;
}

/* ==========================================================================
   Navigation Bar (Flexbox)
   ========================================================================== */
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px 40px;
  background-color: rgba(15, 23, 42, 0.9);
  backdrop-filter: blur(12px);
  position: sticky;
  top: 0;
  z-index: 100;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.logo {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--color-primary);
}

.nav-links a {
  color: var(--text-gray);
  text-decoration: none;
  margin-left: 24px;
  font-weight: 500;
  transition: color 0.2s ease;
}

.nav-links a:hover {
  color: var(--text-white);
}

/* ==========================================================================
   Hero Section (Flexbox Centering)
   ========================================================================== */
.hero {
  min-height: 90vh;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: 40px 20px;
}

.hero-content h1 {
  font-size: 3.5rem;
  font-weight: 800;
  margin-bottom: 16px;
}

.hero-content .accent {
  color: var(--color-primary);
}

.hero-content p {
  font-size: 1.25rem;
  color: var(--text-gray);
  max-width: 600px;
  margin: 0 auto 32px auto;
}

.btn-primary {
  display: inline-block;
  background-color: var(--color-primary);
  color: var(--text-white);
  padding: 12px 28px;
  border-radius: 8px;
  text-decoration: none;
  font-weight: 600;
  border: none;
  cursor: pointer;
  transition: background-color 0.2s ease, transform 0.2s ease;
}

.btn-primary:hover {
  background-color: var(--color-primary-hover);
  transform: translateY(-2px);
}

/* ==========================================================================
   Projects Section (Flexbox wrapping)
   ========================================================================== */
.projects {
  padding: 80px 40px;
  max-width: 1200px;
  margin: 0 auto;
}

.projects h2 {
  font-size: 2.25rem;
  margin-bottom: 40px;
  text-align: center;
}

.projects-grid {
  display: flex;
  flex-wrap: wrap; /* Wraps cards on mobile viewports */
  gap: 24px;
}

.project-card {
  background-color: var(--bg-card);
  border: 1px solid rgba(255, 255, 255, 0.05);
  padding: 32px;
  border-radius: 12px;
  
  /* Flexbox parameters for cards: grow, shrink, default basis width */
  flex: 1 1 350px; 
  
  transition: transform 0.3s ease, border-color 0.3s ease;
}

.project-card:hover {
  transform: translateY(-5px);
  border-color: var(--color-primary);
}

.project-card h3 {
  font-size: 1.5rem;
  margin-bottom: 12px;
}

.project-card p {
  color: var(--text-gray);
  margin-bottom: 24px;
}

.project-link {
  color: var(--color-primary);
  text-decoration: none;
  font-weight: 600;
}

/* ==========================================================================
   Contact Section
   ========================================================================== */
.contact {
  padding: 80px 40px;
  max-width: 600px;
  margin: 0 auto;
}

.contact h2 {
  font-size: 2.25rem;
  margin-bottom: 40px;
  text-align: center;
}

.contact-form {
  display: flex;
  flex-direction: column; /* Vertical stack inputs */
  gap: 16px;
}

.contact-form input,
.contact-form textarea {
  background-color: var(--bg-card);
  border: 1px solid rgba(255, 255, 255, 0.1);
  padding: 16px;
  border-radius: 8px;
  color: var(--text-white);
  font-family: inherit;
}

.contact-form input:focus,
.contact-form textarea:focus {
  outline: 2px solid var(--color-primary);
}

Visual Learning Diagram (Mermaid)

graph TD
    subgraph Mobile-First Portfolio Structure
    Nav[Navbar: flex row / wrap-on-mobile]
    Hero[Hero Section: flex justify-center, align-center]
    Grid[Projects Grid: flex wrap / flex: 1 1 350px]
    Form[Contact Form: flex column / vertical stack]
    end

Responsive Adjustments: Mobile Media Query

Add a media query at the bottom of style.css to adjust padding and layouts on mobile screens under 768px:

@media (max-width: 768px) {
  .navbar {
    flex-direction: column; /* Stack logo and links vertically */
    gap: 12px;
    padding: 16px;
  }
  
  .nav-links a {
    margin: 0 10px;
  }
  
  .hero-content h1 {
    font-size: 2.5rem; /* Scale headings down */
  }
  
  .projects, .contact {
    padding: 60px 20px;
  }
}

Summary

This Personal Portfolio Website uses semantic HTML5 structured wrappers styled using custom CSS variables. Navigation lists, hero blocks, projects grids, and contact inputs are aligned responsively utilizing Flexbox rows, wraps, columns, and mobile media queries.


Related Articles

Next Tutorial

Ready for a more advanced layout? Let's build a SaaS product landing page using CSS Grid: Project: SaaS Landing Page.