Blog

Blog · Templates

Free Portfolio Website Template (HTML & CSS, 2026)

A clean, responsive, accessible personal portfolio template in plain HTML and CSS — hero, projects grid, about and contact sections — ready to copy, customize and deploy.

XCODX Team · 5 min read

This is a free, responsive portfolio website template built with plain HTML and modern CSS — no framework, no build step. It has a hero, a projects grid, an about section and a contact call-to-action, uses CSS custom properties so you can restyle it in seconds, and is accessible and mobile-first out of the box. Copy it, make it yours, and deploy.

What you get

  • A semantic, accessible single-page layout (header, hero, projects, about, contact, footer).
  • A responsive projects grid that reflows with no media queries (auto-fit + minmax).
  • Fluid typography with clamp() and a tidy dark theme via CSS custom properties.
  • Zero dependencies — just two files, works anywhere.

The HTML

Save this as index.html. It’s semantic and screen-reader friendly — one <h1>, labelled navigation, and real landmark elements.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Jane Doe — Frontend Developer</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <header class="site-header">
    <a href="#top" class="logo">Jane Doe</a>
    <nav aria-label="Primary">
      <a href="#projects">Projects</a>
      <a href="#about">About</a>
      <a href="#contact">Contact</a>
    </nav>
  </header>

  <main id="top">
    <section class="hero">
      <p class="eyebrow">Frontend Developer</p>
      <h1>I build fast, accessible web experiences.</h1>
      <p class="lede">I'm Jane, a developer specializing in React, TypeScript and
        modern CSS. I turn ideas into polished, performant products.</p>
      <div class="actions">
        <a class="btn btn-primary" href="#projects">View my work</a>
        <a class="btn btn-ghost" href="#contact">Get in touch</a>
      </div>
    </section>

    <section id="projects" class="section">
      <h2>Selected work</h2>
      <div class="grid">
        <article class="card">
          <h3>Project One</h3>
          <p>What you built, the problem it solved, and the stack you used.</p>
          <a href="#">View project &rarr;</a>
        </article>
        <article class="card">
          <h3>Project Two</h3>
          <p>Keep each description to two short, concrete sentences.</p>
          <a href="#">View project &rarr;</a>
        </article>
        <article class="card">
          <h3>Project Three</h3>
          <p>Lead with impact: what changed because this exists.</p>
          <a href="#">View project &rarr;</a>
        </article>
      </div>
    </section>

    <section id="about" class="section">
      <h2>About me</h2>
      <p class="prose">A short paragraph about who you are, what you love building,
        and what you're looking for. Keep it human and specific.</p>
    </section>

    <section id="contact" class="section">
      <h2>Let's work together</h2>
      <p class="prose">Open to freelance and full-time roles. The fastest way to
        reach me is email.</p>
      <a class="btn btn-primary" href="mailto:[email protected]">Email me</a>
    </section>
  </main>

  <footer class="site-footer">
    <p>&copy; 2026 Jane Doe.</p>
  </footer>
</body>
</html>

The CSS

Save this as styles.css. The design tokens live at the top — edit --accent and --bg and the whole site follows.

:root {
  --bg: #0b0d14;
  --surface: #141824;
  --text: #e8ecf4;
  --muted: #9aa4b8;
  --accent: #6ea8ff;
  --border: #232838;
  --radius: 14px;
  --max: 960px;
  color-scheme: dark;
}
* { box-sizing: border-box; margin: 0; }
body {
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: var(--bg); color: var(--text); line-height: 1.6;
}
a { color: var(--accent); }

.site-header, main, .site-footer { max-width: var(--max); margin-inline: auto; padding: 20px; }
.site-header { display: flex; justify-content: space-between; align-items: center; }
.site-header nav { display: flex; gap: 22px; }
.site-header nav a { color: var(--muted); text-decoration: none; }
.site-header nav a:hover { color: var(--text); }
.logo { font-weight: 700; color: var(--text); text-decoration: none; }

.hero { padding: 72px 0; }
.eyebrow { color: var(--accent); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; font-size: 14px; }
h1 { font-size: clamp(32px, 6vw, 56px); line-height: 1.1; margin: 12px 0 16px; letter-spacing: -.02em; }
.lede { color: var(--muted); font-size: clamp(17px, 2.5vw, 20px); max-width: 46ch; }
.actions { display: flex; gap: 14px; margin-top: 28px; flex-wrap: wrap; }
.btn { display: inline-block; padding: 12px 22px; border-radius: 10px; font-weight: 600; text-decoration: none; }
.btn-primary { background: var(--accent); color: #06080f; }
.btn-ghost { border: 1px solid var(--border); color: var(--text); }
.btn:hover { filter: brightness(1.08); }

.section { padding: 56px 0; border-top: 1px solid var(--border); }
h2 { font-size: clamp(24px, 4vw, 34px); margin-bottom: 28px; letter-spacing: -.01em; }
.prose { color: var(--muted); max-width: 60ch; margin-bottom: 20px; }

.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 20px; }
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 24px; }
.card h3 { margin-bottom: 8px; }
.card p { color: var(--muted); margin-bottom: 14px; }
.card a { text-decoration: none; }

.site-footer { color: var(--muted); border-top: 1px solid var(--border); }

@media (max-width: 560px) {
  .site-header { flex-direction: column; gap: 10px; align-items: flex-start; }
}

How to customize

  • Colors: change --accent, --bg, --surface and --text in :root. For a light theme, flip --bg/--text and set color-scheme: light.
  • Content: replace the name, hero copy, and the three project cards. Add more cards — the grid reflows automatically.
  • Sections: duplicate a <section class="section"> to add experience, skills or testimonials.
  • Fonts: the system font stack is fast and free; to use a web font, add a @font-face and set it on body (see how to optimize CSS).

Deploy it

It’s two static files, so hosting is free and instant on Netlify, Vercel, Cloudflare Pages or GitHub Pages — drag the folder in, or connect a repo. Because there’s no build step, there’s nothing to configure.

Frequently asked questions

Is this portfolio template free to use?
Yes — copy the HTML and CSS and use them for personal or commercial projects. There’s no attribution requirement and no dependencies. It’s plain HTML and CSS, so you fully own and control the code.
How do I make the portfolio template light instead of dark?
Edit the CSS variables in :root: set --bg to a light color (e.g. #ffffff), --surface to a light grey, --text to a dark color, and change color-scheme: dark to light. Because every color references a variable, the whole site switches theme from those few edits.
Do I need a framework or build tools?
No. This template is intentionally plain HTML and CSS — no React, no build step, no dependencies. That makes it fast to load, easy to host anywhere for free, and simple to edit. You can add JavaScript later if you want interactivity.
How do I add more projects?
Copy one of the <article class="card"> blocks inside the projects grid and change its content. The grid uses repeat(auto-fit, minmax(240px, 1fr)), so it automatically arranges any number of cards into a responsive layout with no extra CSS.

Open this template in XCODX Studio to edit and preview it live in your browser — then deploy. See also the landing page template, resume website template and our CSS best practices.