Build a Filmmaker Portfolio Website

Build and deploy a cinematic portfolio site with Vimeo embeds.

Introduction

30 Second Summary

Every filmmaker needs a place to showcase their work online. A polished portfolio site lets collaborators, producers, and audiences watch your films in one place without digging through social media feeds.

In this project, you will build a professional filmmaker portfolio website from scratch using HTML and CSS. Your site will feature embedded video players, a cinematic dark theme, and free hosting so anyone can visit it.

What You'll Build

A dark, cinematic portfolio website with embedded Vimeo players, a responsive layout that works on phones and desktops, and free hosting on GitHub Pages.

By the end of this project, you'll have:

  • A live website at a public URL that anyone can visit to watch your films.
  • A responsive film grid with embedded Vimeo players that resize perfectly on any screen.
  • A codebase you fully understand and can update yourself whenever you make a new film.
  • Secret Mission: Add a JavaScript-powered lightbox that plays your films in a cinematic full-screen overlay when clicked.

Are there any prerequisites?

None. This guide walks you through setting up everything you need, including your code editor and hosting account. All you need is a Mac and a Vimeo account with your films already uploaded.

Before We Start

Every filmmaker needs a place to showcase their work online. A personal portfolio website gives collaborators, producers, and audiences a single link to browse and watch your films.

Before we build the site itself, you need two things: a code editor to write your HTML and CSS, and a place to host your website for free. In this step, you will install VS Code and set up a GitHub account.

In this step, get ready to:
  • Install VS Code (your code editor).
  • Create a GitHub account (your free website host).
  • Create your project folder and open it in VS Code.
Download and install VS Code

VS Code is a free code editor that gives you syntax highlighting, file management, and a clean workspace for writing your website code.

  • Check if you already have VS Code installed by pressing Cmd+Space to open Spotlight and typing Visual Studio Code.

✔️ I see VS Code in the results

You already have VS Code installed. Press Enter to open it, then skip ahead to the next substep.

ⓧ I don't see it

  • Open your browser and go to https://code.visualstudio.com/download.
  • Click the Mac download button to download the .dmg file.
  • Open the downloaded .dmg file.
  • Drag Visual Studio Code.app into the Applications folder.
  • Press Cmd+Space to open Spotlight, type Visual Studio Code, and press Enter to launch it.

VS Code not opening?

If macOS shows a warning that the app is from an unidentified developer, right-click the VS Code icon in Applications, select Open, then click Open again in the dialog.

help me open VS Code on macOS

Create a GitHub account

GitHub is a platform that hosts code. It also offers free website hosting through a feature called GitHub Pages. Your GitHub username will become part of your website URL, so choose one that represents you professionally.

  • Open your browser and go to https://github.com.
  • Click Sign up in the top-right corner.
  • Choose a username that you want in your website URL (for example, if you pick janefilms, your site will live at janefilms.github.io).
  • Enter your email address and set a password.
  • Complete the verification steps that GitHub presents.

Why does my username matter?

GitHub Pages publishes your site at yourusername.github.io. Pick something short and professional since this URL is what you will share with collaborators and producers.

Already have a GitHub account?

If you can log in at github.com, you are all set. Skip ahead to the next substep.

Create your project folder

You need a dedicated folder on your Mac to hold your website files. This folder will contain everything that makes up your portfolio site.

  • Open Finder and navigate to your Desktop.
  • Right-click on an empty area of the Desktop and select New Folder.
  • Name the folder my-portfolio.

Now open this folder in VS Code so you have a workspace ready for your code.

  • Switch to VS Code.
  • Click File in the top menu bar.
  • Click Open Folder.
  • Select the my-portfolio folder on your Desktop, then click Open.

You should see my-portfolio appear in the Explorer sidebar on the left side of VS Code. The folder will be empty for now.

Don't see the sidebar?

If the Explorer sidebar is hidden, press Cmd+Shift+E to toggle it open. You should see your my-portfolio folder name at the top.

help me find my project folder in VS Code's sidebar

Your workspace is ready. Next up, you will build the HTML structure that gives your portfolio its content and shape.

Set Up Your Tools

Before you start writing any code, you need two tools ready to go: a code editor to write your website files, and a hosting account to publish your site to the internet.

VS Code is your code editor. GitHub is where you will host your finished site for free. Your GitHub username becomes part of your live website URL, so choose wisely.

In this step, get ready to:
  • Confirm VS Code is open with your project folder.
  • Identify your GitHub username and your future site URL.
Confirm VS Code has your project folder open

Your code editor is where you will create and edit your website files. The my-portfolio folder in VS Code is your workspace for this entire project.

  • In VS Code, look at the left sidebar (the **Explorer** panel).
  • Confirm you see MY-PORTFOLIO displayed at the top of the sidebar. This is your open project folder.

Don't see the folder in the sidebar?

  • Click File in the top menu bar, then click Open Folder. Navigate to your Desktop and select the my-portfolio folder.
  • If the sidebar is hidden, click View in the top menu bar, then click Explorer to toggle it on.

Still stuck? Help me find my project folder in VS Code.

Note your GitHub username and site URL

GitHub Pages turns any repository into a live website. The URL it gives you is based directly on your GitHub username.

  • Switch to your browser and go to github.com.
  • Click your profile icon in the top-right corner of the page.
  • Your username is displayed at the top of the dropdown menu (it is the text that starts with a lowercase letter or number, not your display name).

Why does your username matter?

When you deploy your site later, GitHub Pages will give you a URL in this format:

https://yourusername.github.io

Replace yourusername with your actual GitHub username. This is the public link anyone can use to visit your portfolio.

  • Make a mental note of your GitHub username. You will use it in Step 4 when you create your repository.

Your tools are ready. Next up, you will build the HTML structure of your portfolio page.

Build Your HTML Page

Your development environment is ready to go. Now it's time to build the actual content of your portfolio site.

Every website starts with HTML, the language that defines what appears on the page and how it's organized. You'll create sections for your navigation, film showcases, bio, and contact info.

In this step, get ready to:
  • Create your index.html file with the full page structure.
  • Add your Vimeo embed codes so visitors can watch your films.
  • Preview the page in your browser to confirm everything is in place.
Create your HTML file

HTML is made up of nested elements called tags. Each tag wraps a piece of content or defines a section of the page.

  • In VS Code, hover over the my-portfolio folder name in the left sidebar.
  • Click the new file icon (it looks like a page with a small plus sign).
  • Type index.html and press Enter.

Why index.html?

Web servers automatically look for a file named index.html when someone visits your site. It's the default entry point for any website.

  • Add the page skeleton, navigation bar, and hero section by copying this code into your empty index.html file:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Your Name - Filmmaker</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <nav class="navbar">
        <a href="#" class="nav-logo">Your Name</a>
        <ul class="nav-links">
            <li><a href="#films">Films</a></li>
            <li><a href="#about">About</a></li>
            <li><a href="#contact">Contact</a></li>
        </ul>
    </nav>

    <section class="hero">
        <h1>Your Name</h1>
        <p class="hero-tagline">Filmmaker</p>
    </section>

What does this code do?

The <!DOCTYPE html> line tells the browser this is a modern HTML5 page. The <head> section contains metadata like your page title and a link to the stylesheet you'll create in the next step.

The <nav> creates a navigation bar with links that jump to different sections on the page. The hero <section> displays your name and title prominently at the top.

  • Save index.html by pressing Cmd+S.

You won't see any visual output yet since the file isn't open in a browser. The next chunk adds your film content.

  • Add the films section, about section, and footer directly below the hero code you just pasted:

    <section id="films" class="films">
        <h2>Films</h2>
        <div class="film-grid">
            <div class="film-card">
                <div class="film-video">
                    <iframe src="https://player.vimeo.com/video/your-video-id-here" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>
                </div>
                <h3>Film Title One</h3>
                <p>Short description of your first film.</p>
            </div>

            <div class="film-card">
                <div class="film-video">
                    <iframe src="https://player.vimeo.com/video/your-video-id-here" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>
                </div>
                <h3>Film Title Two</h3>
                <p>Short description of your second film.</p>
            </div>

            <div class="film-card">
                <div class="film-video">
                    <iframe src="https://player.vimeo.com/video/your-video-id-here" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>
                </div>
                <h3>Film Title Three</h3>
                <p>Short description of your third film.</p>
            </div>
        </div>
    </section>

    <section id="about" class="about">
        <h2>About</h2>
        <p>Write a short bio about yourself here. Mention your background, your approach to filmmaking, and what drives your creative work. Keep it concise and personal.</p>
    </section>

    <footer id="contact" class="footer">
        <h2>Get in Touch</h2>
        <p>For collaborations and inquiries:</p>
        <a href="mailto:your-email-here@example.com" class="contact-link">your-email-here@example.com</a>
    </footer>
</body>
</html>

What does this code do?

The films section uses a film-grid container to hold three film cards. Each card wraps a Vimeo video player (iframe), a title, and a short description.

The about section holds your bio text. The footer provides your contact email as a clickable mailto: link, so visitors can email you directly from the page.

  • Save index.html again with Cmd+S.

You won't see a change yet. You'll preview the page in the browser after adding your real Vimeo video IDs in the next substep.

Seeing red squiggles in VS Code?

Make sure every opening tag (like <div>) has a matching closing tag (</div>). The films section has several nested div elements that need to close in the correct order.

Also check that the second code chunk starts immediately after the hero </section> closing tag with no overlap or missing lines.

Help me fix the tag errors in my index.html file.

✔️ Awesome, I've got everything!

Great. Double check you've saved your file.

ⓧ I'd like to double check the full code

Here is the complete index.html file so far. Make sure yours matches:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Your Name - Filmmaker</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <nav class="navbar">
        <a href="#" class="nav-logo">Your Name</a>
        <ul class="nav-links">
            <li><a href="#films">Films</a></li>
            <li><a href="#about">About</a></li>
            <li><a href="#contact">Contact</a></li>
        </ul>
    </nav>

    <section class="hero">
        <h1>Your Name</h1>
        <p class="hero-tagline">Filmmaker</p>
    </section>

    <section id="films" class="films">
        <h2>Films</h2>
        <div class="film-grid">
            <div class="film-card">
                <div class="film-video">
                    <iframe src="https://player.vimeo.com/video/your-video-id-here" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>
                </div>
                <h3>Film Title One</h3>
                <p>Short description of your first film.</p>
            </div>

            <div class="film-card">
                <div class="film-video">
                    <iframe src="https://player.vimeo.com/video/your-video-id-here" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>
                </div>
                <h3>Film Title Two</h3>
                <p>Short description of your second film.</p>
            </div>

            <div class="film-card">
                <div class="film-video">
                    <iframe src="https://player.vimeo.com/video/your-video-id-here" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>
                </div>
                <h3>Film Title Three</h3>
                <p>Short description of your third film.</p>
            </div>
        </div>
    </section>

    <section id="about" class="about">
        <h2>About</h2>
        <p>Write a short bio about yourself here. Mention your background, your approach to filmmaking, and what drives your creative work. Keep it concise and personal.</p>
    </section>

    <footer id="contact" class="footer">
        <h2>Get in Touch</h2>
        <p>For collaborations and inquiries:</p>
        <a href="mailto:your-email-here@example.com" class="contact-link">your-email-here@example.com</a>
    </footer>
</body>
</html>
Add your Vimeo embed codes

Your HTML currently has placeholder video IDs. You need to replace them with the real IDs from your Vimeo account so the players actually load your films.

  • Open a new browser tab and go to vimeo.com.
  • Sign in and click on any one of your uploaded videos.
  • Look at the URL in your browser's address bar. It will look like https://vimeo.com/123456789. The number at the end is your video ID.
  • Copy that number.

What is a video ID?

Every video on Vimeo has a unique numeric ID. It's the number that appears after vimeo.com/ in the video's URL. This is the same number used in the embed player URL to tell the browser which video to load.

  • Switch back to VS Code.
  • In index.html, find the first occurrence of your-video-id-here inside the iframe tag's src attribute.
  • Select your-video-id-here and replace it with the video ID you just copied.
  • Repeat for the other two film cards, using the video IDs of your second and third films.

Customise your film titles too

While you're editing, replace Film Title One, Film Title Two, and Film Title Three with your actual film names. Update the short descriptions and the your-email-here@example.com placeholder with your real email address.

  • Also replace Your Name (which appears in the nav logo, hero heading, and page title) with your actual name.
  • Save index.html with Cmd+S.
Preview your page

Your HTML file is complete. Time to open it in a browser and confirm everything displays correctly.

  • Open Finder and navigate to the my-portfolio folder on your Desktop.
  • Right-click index.html.
  • Select Open With and choose your browser (Safari or Google Chrome).

You should see your content displayed with default browser styling: black text on a white background, no layout or colours yet. Your Vimeo players should appear and be playable.

Why does it look so plain?

Without CSS (the stylesheet you'll create in the next step), the browser applies its own default styling. That means plain black text, no background colour, and no grid layout. The structure is all there. The visual design comes next.

Vimeo players not loading?

Make sure you replaced your-video-id-here with the actual numeric ID from your Vimeo video URL (just the numbers, no letters or slashes).

Also check that your video's privacy settings on Vimeo allow embedding. Go to your video's settings on vimeo.com and confirm that embedding is not set to Nowhere.

Help me figure out why my Vimeo embeds are not loading.

Your page structure is complete and your films are playable. Next up, you'll transform this plain content into a dark, cinematic design with CSS.

Style Your Site with CSS

Your HTML page is structured and functional, but it still looks like a plain document with default browser styling.

In this step, you will transform your site into a dark, cinematic portfolio using CSS. You will set colors, fonts, and layout rules that make your films the visual focus.

In this step, get ready to:
  • Create a CSS file with base styles, navigation, and hero section.
  • Build a responsive film grid using CSS Grid.
  • Style the about section, footer, and add hover effects.
Create your CSS file and set the foundation

CSS controls how your HTML elements look. You will start by resetting browser defaults and setting the dark color scheme that gives your portfolio its cinematic feel.

  • In VS Code, click the new file icon in the Explorer sidebar.
  • Name the file style.css.
  • Add the following reset and body styles to set your site's foundation:
/* Reset and base styles */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    background-color: #0a0a0a;
    color: #f0f0f0;
    line-height: 1.6;
}

What does this code do?

The reset and body styles establish a consistent starting point for your design.

  • The * selector removes default margins and padding from every element, giving you full control over spacing.
  • The body rule sets the dark background (#0a0a0a), off-white text (#f0f0f0), and a system font stack that loads fast without external dependencies.
  • Save style.css.
  • Refresh your browser. Your page should now have a dark background with light text. The content will look cramped together because you removed all default spacing.

Still seeing white background?

  • Check that your file is named exactly style.css (not styles.css or style.CSS).
  • Verify that index.html has <link rel="stylesheet" href="style.css"> inside the <head> section.
  • Make sure both files are in the same my-portfolio folder.

My page still has a white background after adding CSS styles.

  • Add the navigation styles below your body rule:
/* Navigation */
.navbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 1.5rem 3rem;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    background-color: rgba(10, 10, 10, 0.9);
    z-index: 100;
}

.nav-logo {
    color: #f0f0f0;
    text-decoration: none;
    font-size: 1.2rem;
    font-weight: 600;
}

.nav-links {
    display: flex;
    list-style: none;
    gap: 2rem;
}

.nav-links a {
    color: #999;
    text-decoration: none;
    font-size: 0.9rem;
    transition: color 0.3s ease;
}

.nav-links a:hover {
    color: #f0f0f0;
}

What does this code do?

  • The .navbar uses position: fixed so it stays visible at the top of the page as visitors scroll.
  • The display: flex and justify-content: space-between push your logo to the left and links to the right.
  • The transition on links creates a smooth color fade when visitors hover over them.
  • Save style.css and refresh your browser.
  • You should see a navigation bar pinned to the top with your name on the left and links on the right. Hover over the links to see them fade from gray to white.

Navigation bar overlapping your content?

This is expected for now. The fixed navbar sits on top of your content. The hero section padding you add next will push the content below it.

  • Add the hero section styles below your navigation code:
/* Hero section */
.hero {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    min-height: 80vh;
    text-align: center;
    padding: 6rem 2rem 4rem;
}

.hero h1 {
    font-size: 4rem;
    font-weight: 300;
    letter-spacing: 0.1em;
    margin-bottom: 0.5rem;
}

.hero-tagline {
    font-size: 1.2rem;
    color: #999;
    letter-spacing: 0.3em;
    text-transform: uppercase;
}

What does this code do?

  • The min-height: 80vh makes the hero take up at least 80% of the screen height, giving your name dramatic presence.
  • The light font-weight: 300 and wide letter-spacing create an elegant, cinematic title treatment.
  • The padding: 6rem 2rem 4rem adds generous top padding so the content clears the fixed navigation bar.
  • Save style.css and refresh your browser.
  • Your name should appear large and centered in the middle of the screen, with the tagline in small uppercase text below it.

Name not centered on the page?

  • Confirm that your hero section in index.html uses class="hero" on the <section> element.
  • Check for typos in your CSS selector. It must be .hero with a dot prefix.

My hero section text isn't centering properly.

Style the film grid

CSS Grid lets you arrange elements in rows and columns. You will use it to display your films in a clean two-column layout.

  • Add the films section and grid layout styles below your hero code:
/* Films section */
.films {
    padding: 4rem 3rem;
    max-width: 1200px;
    margin: 0 auto;
}

.films h2 {
    font-size: 1.5rem;
    font-weight: 300;
    letter-spacing: 0.1em;
    margin-bottom: 3rem;
    text-transform: uppercase;
}

.film-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 2.5rem;
}

What does this code do?

  • The max-width: 1200px and margin: 0 auto keep your content centered and prevent it from stretching too wide on large monitors.
  • The grid-template-columns: repeat(2, 1fr) creates two equal-width columns. The gap adds space between each card.
  • Save style.css and refresh your browser.
  • Your films should now appear in two columns below the hero section. They will look rough because the cards themselves are unstyled.
  • Add the film card and video styles below your grid code:
.film-card {
    background-color: #141414;
    border-radius: 8px;
    overflow: hidden;
    transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.film-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 8px 30px rgba(255, 255, 255, 0.05);
}

.film-video {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
}

.film-video iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

.film-card h3 {
    padding: 1.2rem 1.2rem 0.3rem;
    font-size: 1.1rem;
    font-weight: 500;
}

.film-card p {
    padding: 0 1.2rem 1.2rem;
    font-size: 0.9rem;
    color: #999;
}

What does this code do?

  • Each .film-card gets a dark background, rounded corners, and a hover effect that lifts the card with a subtle glow.
  • The aspect-ratio: 16 / 9 on .film-video keeps your Vimeo players at the correct widescreen proportion regardless of screen size.
  • Positioning the iframe absolutely inside a relative container makes the video fill the entire card width while maintaining its aspect ratio.
  • Save style.css and refresh your browser.
  • Your film cards should now have dark backgrounds, rounded corners, and properly sized Vimeo players. Hover over a card to see it lift slightly with a soft white glow.

Vimeo players look squished or overflowing?

  • Confirm that .film-video has position: relative and the iframe inside has position: absolute. Both are required for the sizing to work.
  • Make sure your HTML wraps each <iframe> in a <div class="film-video"> container.

My Vimeo iframes aren't sizing correctly in the film cards.

Style the about section and footer

The remaining sections need clean typography with comfortable reading widths. You will also add a responsive layout so the site looks great on mobile.

  • Add the about section styles below your film card code:
/* About section */
.about {
    padding: 4rem 3rem;
    max-width: 700px;
    margin: 0 auto;
}

.about h2 {
    font-size: 1.5rem;
    font-weight: 300;
    letter-spacing: 0.1em;
    margin-bottom: 1.5rem;
    text-transform: uppercase;
}

.about p {
    font-size: 1rem;
    color: #ccc;
    line-height: 1.8;
}

What does this code do?

  • The max-width: 700px keeps text lines short and easy to read. Long lines of text are harder to follow visually.
  • The line-height: 1.8 adds generous spacing between lines, making the bio comfortable to read.
  • Add the footer and contact link styles below your about section code:
/* Footer */
.footer {
    padding: 4rem 3rem;
    text-align: center;
    border-top: 1px solid #222;
    margin-top: 4rem;
}

.footer h2 {
    font-size: 1.5rem;
    font-weight: 300;
    letter-spacing: 0.1em;
    margin-bottom: 1rem;
    text-transform: uppercase;
}

.footer p {
    color: #999;
    margin-bottom: 0.5rem;
}

.contact-link {
    color: #f0f0f0;
    text-decoration: none;
    border-bottom: 1px solid #555;
    padding-bottom: 2px;
    transition: border-color 0.3s ease;
}

.contact-link:hover {
    border-color: #f0f0f0;
}

What does this code do?

  • The border-top: 1px solid #222 creates a subtle divider line separating the footer from the content above.
  • The .contact-link uses a bottom border instead of the default underline, with a smooth hover transition that brightens the line.
  • Now add the responsive styles at the very end of your file. These adjust the layout for mobile screens:
/* Responsive design */
@media (max-width: 768px) {
    .navbar {
        padding: 1rem 1.5rem;
    }

    .nav-links {
        gap: 1rem;
    }

    .hero h1 {
        font-size: 2.5rem;
    }

    .hero-tagline {
        font-size: 1rem;
    }

    .films {
        padding: 3rem 1.5rem;
    }

    .film-grid {
        grid-template-columns: 1fr;
    }

    .about {
        padding: 3rem 1.5rem;
    }

    .footer {
        padding: 3rem 1.5rem;
    }
}

What does this code do?

The @media (max-width: 768px) block applies styles only when the browser window is 768 pixels wide or less (roughly tablet and phone sizes).

  • The grid-template-columns: 1fr switches the film grid from two columns to a single column so cards stack vertically on small screens.
  • Font sizes and padding are reduced to fit comfortably on narrower screens.
  • Save style.css and refresh your browser.
  • Your site should now show a complete dark cinematic design with a styled about section, a centered footer with a subtle top border, and the contact link with a hover effect.
  • Resize your browser window to a narrow width. The film grid should collapse to a single column and the text should remain readable.

Responsive layout not changing when you resize?

  • Make sure the @media block is at the very end of your style.css file, not nested inside another rule.
  • Check that all curly braces are properly closed. The @media block has its own opening and closing brace wrapping all the rules inside.
  • Verify that your index.html includes <meta name="viewport" content="width=device-width, initial-scale=1.0"> in the head section.

My responsive media query doesn't seem to be working.

✔️ Awesome, I've got everything!

Great. Double check you have saved style.css and that your browser shows the full dark design.

ⓧ I'd like to double check the full code

Here is the complete style.css file. Compare yours against this:

/* Reset and base styles */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    background-color: #0a0a0a;
    color: #f0f0f0;
    line-height: 1.6;
}

/* Navigation */
.navbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 1.5rem 3rem;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    background-color: rgba(10, 10, 10, 0.9);
    z-index: 100;
}

.nav-logo {
    color: #f0f0f0;
    text-decoration: none;
    font-size: 1.2rem;
    font-weight: 600;
}

.nav-links {
    display: flex;
    list-style: none;
    gap: 2rem;
}

.nav-links a {
    color: #999;
    text-decoration: none;
    font-size: 0.9rem;
    transition: color 0.3s ease;
}

.nav-links a:hover {
    color: #f0f0f0;
}

/* Hero section */
.hero {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    min-height: 80vh;
    text-align: center;
    padding: 6rem 2rem 4rem;
}

.hero h1 {
    font-size: 4rem;
    font-weight: 300;
    letter-spacing: 0.1em;
    margin-bottom: 0.5rem;
}

.hero-tagline {
    font-size: 1.2rem;
    color: #999;
    letter-spacing: 0.3em;
    text-transform: uppercase;
}

/* Films section */
.films {
    padding: 4rem 3rem;
    max-width: 1200px;
    margin: 0 auto;
}

.films h2 {
    font-size: 1.5rem;
    font-weight: 300;
    letter-spacing: 0.1em;
    margin-bottom: 3rem;
    text-transform: uppercase;
}

.film-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 2.5rem;
}

.film-card {
    background-color: #141414;
    border-radius: 8px;
    overflow: hidden;
    transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.film-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 8px 30px rgba(255, 255, 255, 0.05);
}

.film-video {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
}

.film-video iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

.film-card h3 {
    padding: 1.2rem 1.2rem 0.3rem;
    font-size: 1.1rem;
    font-weight: 500;
}

.film-card p {
    padding: 0 1.2rem 1.2rem;
    font-size: 0.9rem;
    color: #999;
}

/* About section */
.about {
    padding: 4rem 3rem;
    max-width: 700px;
    margin: 0 auto;
}

.about h2 {
    font-size: 1.5rem;
    font-weight: 300;
    letter-spacing: 0.1em;
    margin-bottom: 1.5rem;
    text-transform: uppercase;
}

.about p {
    font-size: 1rem;
    color: #ccc;
    line-height: 1.8;
}

/* Footer */
.footer {
    padding: 4rem 3rem;
    text-align: center;
    border-top: 1px solid #222;
    margin-top: 4rem;
}

.footer h2 {
    font-size: 1.5rem;
    font-weight: 300;
    letter-spacing: 0.1em;
    margin-bottom: 1rem;
    text-transform: uppercase;
}

.footer p {
    color: #999;
    margin-bottom: 0.5rem;
}

.contact-link {
    color: #f0f0f0;
    text-decoration: none;
    border-bottom: 1px solid #555;
    padding-bottom: 2px;
    transition: border-color 0.3s ease;
}

.contact-link:hover {
    border-color: #f0f0f0;
}

/* Responsive design */
@media (max-width: 768px) {
    .navbar {
        padding: 1rem 1.5rem;
    }

    .nav-links {
        gap: 1rem;
    }

    .hero h1 {
        font-size: 2.5rem;
    }

    .hero-tagline {
        font-size: 1rem;
    }

    .films {
        padding: 3rem 1.5rem;
    }

    .film-grid {
        grid-template-columns: 1fr;
    }

    .about {
        padding: 3rem 1.5rem;
    }

    .footer {
        padding: 3rem 1.5rem;
    }
}

Your site now looks like a professional filmmaker portfolio. Next up, you will deploy it to the internet so anyone can visit it with a real URL.

Deploy Your Site to GitHub Pages

Your portfolio looks polished locally, but nobody else can see it yet.

In this step, you will upload your files to GitHub and turn on GitHub Pages, a free hosting service that publishes your site at a public URL.

In this step, get ready to:
  • Create a GitHub repository named after your username.
  • Upload your HTML and CSS files to the repository.
  • Enable GitHub Pages so your site goes live at a public URL.
Create your repository

GitHub Pages requires a repository with a specific name to serve your site. The name must match the pattern yourusername.github.io, where the first part is your actual GitHub username.

  • Go to github.com and sign in to your account.
  • Click the + icon in the top-right corner of any page.
  • Click New repository.
  • In the Repository name field, type yourusername.github.io, replacing yourusername with your actual GitHub username.
  • Make sure Public is selected (GitHub Pages requires this).
  • Check the box labeled Add a README file.
  • Click Create repository.

Why does the name matter?

GitHub Pages uses the repository name to determine your site's URL. A repository named yourusername.github.io automatically becomes your site's address. Any other name would require extra configuration.

Repository name already taken?

If you see an error that the repository name is unavailable, you may already have a repository with this name. Go to your profile repositories list and delete or rename the existing one first.

Help me fix a repository name conflict on GitHub.

Upload your files

Now you will add your website files to the repository using GitHub's web upload feature. No command line needed.

  • In your new repository page, click Add file (above the file list).
  • Click Upload files.
  • Open Finder and navigate to the my-portfolio folder on your Desktop.
  • Drag both index.html and style.css from that folder into the upload area on the GitHub page.
  • Wait for both files to appear in the upload list.
  • In the Commit message field, type Add portfolio site.
  • Click Commit changes.

You should now see index.html, style.css, and README.md listed in your repository's file list.

Files not appearing after upload?

Make sure you clicked Commit changes after dragging the files in. If you navigated away before committing, the upload was not saved. Return to the repository and try the upload again.

Help me upload files to my GitHub repository.

Enable GitHub Pages and visit your live site

Your files are on GitHub, but the site is not live yet. You need to tell GitHub Pages which branch and folder to serve from.

  • Click the Settings tab at the top of your repository page.
  • In the left sidebar, under Code and automation, click Pages.
  • Under Build and deployment > Source, select Deploy from a branch.
  • Under Branch, select main from the first dropdown.
  • Select / (root) from the folder dropdown.
  • Click Save.

What is Deploy from a branch?

This tells GitHub Pages to take the files on your main branch and serve them as a website. The / (root) folder setting means it looks for your index.html at the top level of the repository.

GitHub Pages can take up to 10 minutes to publish your site. Wait 1-2 minutes, then try visiting your URL.

  • Open a new browser tab.
  • Type your site's URL in the address bar: https:// followed by your repository name (e.g. https://yourusername.github.io).
  • Press Enter.

You should see your full portfolio site with the dark cinematic design, your films section with working Vimeo players, your about section, and your contact footer.

✔️ I see my portfolio site

Your site is live. Anyone with the URL can now visit your portfolio and watch your films.

ⓧ I see a 404 page

  • Double-check that your repository is named exactly yourusername.github.io (with your real username, all lowercase).
  • Confirm that index.html exists at the root of your repository (not inside a subfolder).
  • Go back to Settings > Pages and verify the branch is set to main and the folder is / (root).
  • Wait a few more minutes. Changes can take up to 10 minutes to publish.

Help me fix a 404 error on my GitHub Pages site.

ⓧ I see the README instead of my site

This means your index.html file was not uploaded correctly. GitHub Pages serves README.md when it cannot find an index.html file.

  • Go to your repository's main page and check if index.html appears in the file list.
  • If it is missing, repeat the upload step: click Add file > Upload files and drag index.html in again.
  • Make sure the file is named exactly index.html (lowercase, no spaces). The name is case-sensitive.

Help me figure out why GitHub Pages shows my README instead of my website.

Secret mission

Add a Video Lightbox

Your portfolio plays videos inline right now, but professional film sites use a cinematic lightbox. When a visitor clicks a film, the screen goes dark and the video plays large and centered. Ready to add that polished, immersive experience to your site?

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely on your local machine and is hosted for free on GitHub Pages. There are no ongoing costs or paid services to worry about.

Decide whether to keep your resources running, pause them to come back later, or delete them entirely.

Resources you used:

  • Local my-portfolio folder on your Desktop (contains index.html, style.css, script.js).
  • GitHub repository (yourusername.github.io) with GitHub Pages enabled.
  • VS Code (installed application).
  • GitHub account.

Keep everything running

No action needed. Choose this if you plan to keep updating your portfolio with new films or want to experiment further with HTML, CSS, and JavaScript.

  • Your site stays live at your GitHub Pages URL for anyone to visit.
  • VS Code remains available for editing your files anytime.
  • Your local my-portfolio folder stays on your Desktop for quick access.

Pause - I'll come back to this later

Your site will stay live on GitHub Pages at no cost, so there is nothing to pause on the hosting side. You can close VS Code to free up memory on your machine.

  • Quit VS Code by pressing Cmd+Q.
  • Your my-portfolio folder and GitHub repository remain intact for when you return.

Delete - I don't want to use this again

Remove all project resources from your machine and GitHub. Follow each step below.

  • Delete your local project folder by opening Terminal and running:
rm -rf ~/Desktop/my-portfolio
  • Delete your GitHub repository:
  • Go to your repository page on github.com.
  • Click Settings (under your repository name).
  • Scroll down to the Danger Zone section.
  • Click Delete this repository.
  • Click I want to delete this repository.
  • Read the warnings and click I have read and understand these effects.
  • Type your repository name to confirm, then click Delete this repository.

Deleting the repository automatically removes your GitHub Pages site. Your URL will stop working within a few minutes.

  • Uninstall VS Code (optional):
  • Open Finder and go to Applications.
  • Right-click Visual Studio Code and select Move to Trash.
  • To also remove settings and extensions, open Terminal and run:
rm -rf ~/Library/Application\ Support/Code
rm -rf ~/.vscode
  • Delete your GitHub account (optional). Only do this if you created the account solely for this project:
  • On github.com, click your profile photo in the top-right corner.
  • Select Settings.
  • In the left sidebar, click Account.
  • Scroll to the bottom and click Delete your account.
  • Follow the confirmation prompts to permanently delete your account.

That's a Wrap!

That's a Wrap!

Nice work! You just built a professional filmmaker portfolio website from scratch and published it to the internet for free.

You've learned how to:

  • Built a complete HTML page from scratch with semantic sections including navigation, hero, film grid, about, and footer.
  • Styled a responsive, cinematic dark-theme website using CSS Grid and hover effects that adapt to any screen size.
  • Embedded Vimeo videos that play directly on your site and deployed the whole thing to GitHub Pages at a public URL for free.
  • Secret Mission: Added a JavaScript-powered lightbox that plays films in a cinematic full-screen overlay.

Ready to quiz yourself?