Jon Jones Fan Page

Build a styled fan page using semantic HTML and modern CSS.

Introduction

30 Second Summary

Every fan has a favourite fighter, athlete, or artist they want to celebrate. Building a dedicated page for them is one of the most satisfying ways to learn how the web actually works.

In this project, you will build a single-page fan site for UFC fighter Jon "Bones" Jones using HTML and CSS. You will structure content with semantic elements and style it with a dark, fight-night themed design.

What You'll Build

A dark-themed fan page featuring a bold hero section, career stats cards, a highlights timeline, and a styled footer, built entirely with HTML and CSS.

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

  • A complete index.html file using semantic HTML elements (header, main, section, footer) that give your page clear, meaningful structure.
  • A style.css file with modern CSS styling including flexbox layout, CSS custom properties, and Google Fonts.
  • A polished fan page with interactive hover effects and smooth CSS transitions, viewable in any browser.
  • Secret Mission: Make the page fully responsive for mobile devices using CSS media queries.

Are there any prerequisites?

None beyond basic computer literacy. You just need a text editor (VS Code) and a web browser (Google Chrome recommended). No previous coding experience is required.

Before We Start

Before We Start...

Set Up Your Project

Every web page needs a skeleton before you can add content and style. This skeleton is called the HTML boilerplate. It tells the browser what language the page uses, how to scale on different screens, and where to find the stylesheet.

In this step, you'll create your project folder, add the two files every web page needs, and verify everything loads correctly in Google Chrome.

In this step, get ready to:
  • Create a project folder and open it in VS Code.
  • Create the HTML and CSS files with boilerplate code.
  • Preview the page in Google Chrome and confirm it loads correctly.
Create your project folder

Your project needs a dedicated folder to keep all its files organized. You'll create this folder on your Desktop so it's easy to find.

  • In VS Code, open the integrated terminal by pressing Ctrl+` (backtick key, usually above Tab).

Can't find the backtick key?

You can also open the terminal from the menu: click View in the top menu bar, then click Terminal.

  • Move to your Desktop and create the project folder by running these commands:
cd ~/Desktop
mkdir jon-jones-fan-page
  • Confirm the folder was created by running:
ls

You should see jon-jones-fan-page listed in the output.

Don't see the folder?

Make sure you typed the folder name exactly as shown. If you get a "Permission denied" error, try running the cd ~/Desktop command first to make sure you're in the right place.

Help me troubleshoot my folder creation

  • Now open this folder in VS Code. Click File in the top menu bar.
  • Click Open Folder.
  • Navigate to your Desktop, select the jon-jones-fan-page folder, and click Open.

VS Code's Explorer sidebar (the top icon on the left) should now show the folder name jon-jones-fan-page at the top.

Create the project files and add HTML boilerplate

Every web project needs at least two files. The index.html file holds the page content. The style.css file controls how that content looks.

  • In VS Code's Explorer sidebar, hover over the folder name and click the New File icon (it looks like a page with a plus sign).
  • Type index.html and press Enter.
  • Click the New File icon again.
  • Type style.css and press Enter.

You should now see both files listed in the Explorer sidebar.

  • Click on index.html in the Explorer to open it in the editor.
  • Add the HTML boilerplate by pasting the following code into the file:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Jon Bones Jones</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
</body>
</html>

What does this code do?

  • <!DOCTYPE html> tells the browser this is a modern HTML5 document.
  • <meta charset="UTF-8"> sets the character encoding so special characters display correctly.
  • <meta name="viewport" ...> ensures the page scales properly on phones and tablets.
  • <title> sets the text that appears in the browser tab.
  • <link rel="stylesheet" href="style.css"> connects your CSS file so styles apply to the page.
  • Save index.html by pressing Cmd+S (macOS) or Ctrl+S (Windows).

Seeing a dot on the file tab?

A dot or circle on the tab name means the file has unsaved changes. Press Cmd+S (macOS) or Ctrl+S (Windows) to save. The dot disappears once saved.

Help me save my file in VS Code

✔️ Awesome, I've got everything!

Great. Double check you've saved your file before moving on.

ⓧ I'd like to double check the full code

Here's what your index.html should look like so far:

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

Your style.css file should be empty for now.

Preview your page in Google Chrome

Your HTML file is ready. Now you need to open it in a browser to confirm everything is wired up correctly.

  • In VS Code's Explorer sidebar, right-click on index.html.
  • Click Reveal in Finder (macOS) or Reveal in File Explorer (Windows).
  • Double-click index.html in the file browser to open it in your default browser.

Not opening in Chrome?

If the file opens in a different browser, right-click index.html in your file browser and select Open With > Google Chrome.

  • Check that the browser tab displays Jon Bones Jones as the page title.
  • Open DevTools by pressing F12 (or Cmd+Option+I on macOS).
  • Click the Console tab and confirm there are no red error messages.

You should see a completely blank white page. That's expected. The page has no visible content in the <body> yet.

Seeing an error in the Console?

If you see a message about style.css not being found, make sure the file exists in the same folder as index.html. Check that the filename is spelled exactly style.css (all lowercase, no extra spaces).

If the tab title doesn't say Jon Bones Jones, double check the <title> tag in your HTML matches the code above exactly.

Help me fix my page preview

Your project skeleton is in place. Next up, you'll fill the <body> with the full HTML structure of the fan page.

Build the HTML Structure

Your blank page is loading successfully in the browser. Now it's time to fill that empty <body> with real content.

HTML isn't just about displaying text. Semantic HTML elements like header, main, and footer tell the browser (and screen readers) what each piece of content represents. In this step, you'll structure the entire fan page using these meaningful elements.

In this step, get ready to:
  • Add a hero header with the fighter's name, tagline, and quick facts.
  • Build the career stats and highlights sections inside a main element.
  • Add a footer with a credit line and an external link.
Add the hero header

The header is the first thing visitors see. You'll use a header element to group the fighter's name, tagline, and quick facts together at the top of the page.

  • In index.html, find the empty <body> tags.
  • Add the following code between the opening and closing body tags:
    <header class="hero">
        <h1>Jon "Bones" Jones</h1>
        <p class="tagline">The Greatest of All Time</p>
        <ul class="quick-facts">
            <li>Record: 28-1-0</li>
            <li>Division: Heavyweight</li>
            <li>Nickname: Bones</li>
        </ul>
    </header>

What does this code do?

  • <header class="hero"> creates a semantic header section. The class="hero" gives it a hook for styling later.
  • <h1> is the main page heading. Every page should have exactly one h1.
  • <ul class="quick-facts"> creates an unordered list. Each <li> is one fact about the fighter.
  • Save index.html.
  • Refresh your browser. You should see "Jon "Bones" Jones" as a large heading, "The Greatest of All Time" as smaller text below it, and three bullet points with his record, division, and nickname.

Don't see any text on the page?

  • Make sure you pasted the code between the opening <body> and closing </body> tags, not inside the <head> section.
  • Check that every opening tag has a matching closing tag. Look for </header>, </ul>, and </li> at the end of each element.
  • Confirm you saved the file. Look for the dot indicator on the index.html tab in VS Code that disappears after saving.

Why isn't my HTML showing in the browser?

Add the career stats section

The <main> element wraps the primary content of your page. Inside it, you'll create a stats section with a grid of cards showing Jones' career numbers.

  • In index.html, add the following code directly below the closing </header> tag:
    <main>
        <section class="stats">
            <h2>Career Stats</h2>
            <div class="stats-grid">
                <div class="stat-card">
                    <span class="stat-number">59%</span>
                    <span class="stat-label">Striking Accuracy</span>
                </div>
                <div class="stat-card">
                    <span class="stat-number">95%</span>
                    <span class="stat-label">Takedown Defense</span>
                </div>
                <div class="stat-card">
                    <span class="stat-number">11</span>
                    <span class="stat-label">KO/TKO Wins</span>
                </div>
                <div class="stat-card">
                    <span class="stat-number">7</span>
                    <span class="stat-label">Submission Wins</span>
                </div>
            </div>
        </section>

What does this code do?

  • <main> tells the browser this is the core content area of the page, separate from the header and footer.
  • <section class="stats"> groups related content under a theme. Each section gets its own heading (<h2>).
  • Each stat-card div contains a stat-number and a stat-label. The class names describe what the content IS, making it easy to style later.
  • Save index.html and refresh your browser.
  • You should see a "Career Stats" heading followed by the four stat values (59%, 95%, 11, 7) with their labels.

Only seeing the header, not the stats?

  • Make sure you placed this code after the closing </header> tag, not inside the header.
  • Count your closing </div> tags. You need one for each stat-card (4), one for stats-grid, totalling 5.

Help me fix my nested HTML tags.

Add the highlights and footer

The second section presents Jones' career timeline as an ordered list. After the main content, you'll close it off with a footer containing credits and a link to his official profile.

  • In index.html, add the following code directly below the closing </section> tag of the stats section (the one right after the last </div>):
        <section class="highlights">
            <h2>Career Highlights</h2>
            <ol class="timeline">
                <li>UFC debut at UFC 87 against Andre Gusmao (2008)</li>
                <li>Became youngest UFC champion at age 23, defeating Shogun Rua at UFC 128 (2011)</li>
                <li>Eight successful title defenses at light heavyweight, breaking the division record</li>
                <li>Won vacant heavyweight title by submitting Ciryl Gane at UFC 285 (2023)</li>
                <li>Retained heavyweight title with spinning back kick KO of Stipe Miocic at UFC 309 (2024)</li>
            </ol>
        </section>
    </main>

    <footer>
        <p>Built with HTML and CSS</p>
        <p><a href="https://www.ufc.com/athlete/jon-jones" target="_blank">Official UFC Profile</a></p>
    </footer>

What does this code do?

  • <ol class="timeline"> is an ordered list. The browser automatically numbers each <li> item, which is perfect for a chronological timeline.
  • </main> closes the main content area you opened in the previous chunk.
  • <footer> marks the page's closing section. The target="_blank" attribute on the link opens the UFC profile in a new tab so visitors don't leave your page.
  • Save index.html and refresh your browser.
  • You should see a numbered list of 5 career highlights, followed by "Built with HTML and CSS" and a clickable "Official UFC Profile" link at the bottom.
  • Click the "Official UFC Profile" link to confirm it opens the UFC page in a new tab.

Link not opening in a new tab?

  • Check that target="_blank" is inside the <a> tag, not outside the closing >.
  • Make sure the href value is wrapped in quotes: href="https://www.ufc.com/athlete/jon-jones".

Help me fix my anchor tag.

Why use semantic elements instead of divs?

You could build this entire page using only <div> elements and it would look the same in a browser. The difference is meaning.

Semantic elements like header, main, section, and footer help screen readers navigate the page. They also make your code easier to read when you come back to it later.

✔️ Awesome, I've got everything!

Great. Double check you've saved your file before moving on.

ⓧ I'd like to double check the full code

Here's the complete index.html at this point:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Jon Bones Jones</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <header class="hero">
        <h1>Jon "Bones" Jones</h1>
        <p class="tagline">The Greatest of All Time</p>
        <ul class="quick-facts">
            <li>Record: 28-1-0</li>
            <li>Division: Heavyweight</li>
            <li>Nickname: Bones</li>
        </ul>
    </header>

    <main>
        <section class="stats">
            <h2>Career Stats</h2>
            <div class="stats-grid">
                <div class="stat-card">
                    <span class="stat-number">59%</span>
                    <span class="stat-label">Striking Accuracy</span>
                </div>
                <div class="stat-card">
                    <span class="stat-number">95%</span>
                    <span class="stat-label">Takedown Defense</span>
                </div>
                <div class="stat-card">
                    <span class="stat-number">11</span>
                    <span class="stat-label">KO/TKO Wins</span>
                </div>
                <div class="stat-card">
                    <span class="stat-number">7</span>
                    <span class="stat-label">Submission Wins</span>
                </div>
            </div>
        </section>

        <section class="highlights">
            <h2>Career Highlights</h2>
            <ol class="timeline">
                <li>UFC debut at UFC 87 against Andre Gusmao (2008)</li>
                <li>Became youngest UFC champion at age 23, defeating Shogun Rua at UFC 128 (2011)</li>
                <li>Eight successful title defenses at light heavyweight, breaking the division record</li>
                <li>Won vacant heavyweight title by submitting Ciryl Gane at UFC 285 (2023)</li>
                <li>Retained heavyweight title with spinning back kick KO of Stipe Miocic at UFC 309 (2024)</li>
            </ol>
        </section>
    </main>

    <footer>
        <p>Built with HTML and CSS</p>
        <p><a href="https://www.ufc.com/athlete/jon-jones" target="_blank">Official UFC Profile</a></p>
    </footer>
</body>
</html>

Your page has all its content in place, structured with meaningful semantic elements. Next up, you'll transform this plain text into a dark, fight-night themed design using CSS.

Style the Page Layout and Typography

Your HTML is structured and all the content is visible in the browser. The problem is it looks like a plain document from 1995.

In this step, you will transform that unstyled text into a dark, fight-night themed page using CSS. You will load custom fonts, define a color palette, and use flexbox to arrange the stat cards in a row.

In this step, get ready to:
  • Load Google Fonts and define CSS custom properties for colors and spacing.
  • Style the hero header with flexbox centering and bold typography.
  • Lay out the stats grid and highlights timeline with flexbox and accent borders.
Add Google Fonts and define base styles

Web fonts let you use typefaces beyond what the learner's computer has installed. Google Fonts hosts hundreds of free fonts you can load with a single link tag.

  • In VS Code, open index.html.
  • Find this line in the <head> section:
<link rel="stylesheet" href="style.css">
  • Add this new line directly above it:
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Oswald:wght@400;700&family=Inter:wght@400;600&display=swap">

What does this link do?

This loads two font families from Google's servers: Oswald (for bold headings) and Inter (for clean body text). The display=swap parameter tells the browser to show text immediately with a fallback font, then swap in the custom font once it finishes loading.

  • Save index.html.

Now you will define the color palette and base page styles. CSS custom properties (also called CSS variables) let you store values once and reuse them everywhere. When you want to change a color later, you only edit one line.

  • Switch to style.css and add the following code:
/* Define reusable colors, fonts, and spacing */
:root {
    --bg-dark: #1a1a2e;
    --bg-card: #16213e;
    --text-light: #eaeaea;
    --accent-gold: #d4af37;
    --font-heading: 'Oswald', sans-serif;
    --font-body: 'Inter', sans-serif;
    --spacing-sm: 1rem;
    --spacing-md: 2rem;
    --spacing-lg: 4rem;
}

/* Remove default browser margins and use consistent box-sizing */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* Apply the dark background and light text to the whole page */
body {
    font-family: var(--font-body);
    background-color: var(--bg-dark);
    color: var(--text-light);
    line-height: 1.6;
}

What does this code do?

The :root block defines variables you can reference anywhere using var(--name). This keeps your colors and spacing consistent across the entire stylesheet.

The * selector targets every element on the page, stripping away default browser styles. The body rule applies the dark background, light text, and Inter font as the default for all content.

  • Save style.css and refresh your browser.
  • You should see the page background turn dark navy and all text turn light gray. The fonts will look cleaner thanks to Inter loading.

Still seeing a white background?

Make sure the Google Fonts link appears above the style.css link in your HTML head. If it comes after, the fonts might not load before your styles try to use them.

Also confirm that your style.css file is saved in the same folder as index.html. The href="style.css" path assumes they are side by side.

Help me figure out why my CSS isn't loading.

✔️ Awesome, I've got everything!

Great. Double check you have saved both files before moving on.

ⓧ I'd like to double check the full code

Here is the full index.html so far:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Jon Bones Jones</title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Oswald:wght@400;700&family=Inter:wght@400;600&display=swap">
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <header class="hero">
        <h1>Jon "Bones" Jones</h1>
        <p class="tagline">The Greatest of All Time</p>
        <ul class="quick-facts">
            <li>Record: 28-1-0</li>
            <li>Division: Heavyweight</li>
            <li>Nickname: Bones</li>
        </ul>
    </header>

    <main>
        <section class="stats">
            <h2>Career Stats</h2>
            <div class="stats-grid">
                <div class="stat-card">
                    <span class="stat-number">59%</span>
                    <span class="stat-label">Striking Accuracy</span>
                </div>
                <div class="stat-card">
                    <span class="stat-number">95%</span>
                    <span class="stat-label">Takedown Defense</span>
                </div>
                <div class="stat-card">
                    <span class="stat-number">11</span>
                    <span class="stat-label">KO/TKO Wins</span>
                </div>
                <div class="stat-card">
                    <span class="stat-number">7</span>
                    <span class="stat-label">Submission Wins</span>
                </div>
            </div>
        </section>

        <section class="highlights">
            <h2>Career Highlights</h2>
            <ol class="timeline">
                <li>UFC debut at UFC 87 against Andre Gusmao (2008)</li>
                <li>Became youngest UFC champion at age 23, defeating Shogun Rua at UFC 128 (2011)</li>
                <li>Eight successful title defenses at light heavyweight, breaking the division record</li>
                <li>Won vacant heavyweight title by submitting Ciryl Gane at UFC 285 (2023)</li>
                <li>Retained heavyweight title with spinning back kick KO of Stipe Miocic at UFC 309 (2024)</li>
            </ol>
        </section>
    </main>

    <footer>
        <p>Built with HTML and CSS</p>
        <p><a href="https://www.ufc.com/athlete/jon-jones" target="_blank">Official UFC Profile</a></p>
    </footer>
</body>
</html>
Style the hero header section

The hero section is the first thing visitors see. You will use flexbox to center the content vertically in a column and add a gold border along the bottom to separate it from the rest of the page.

  • In style.css, add the following code below the body block:
/* Center the hero content in a column layout */
.hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: var(--spacing-lg) var(--spacing-md);
    border-bottom: 4px solid var(--accent-gold);
}

/* Style the fighter name with bold uppercase Oswald */
.hero h1 {
    font-family: var(--font-heading);
    font-size: 3.5rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 2px;
    color: var(--accent-gold);
}

/* Italic tagline beneath the name */
.tagline {
    font-size: 1.25rem;
    margin-top: 0.5rem;
    font-style: italic;
}

/* Display quick facts in a horizontal row */
.quick-facts {
    list-style: none;
    display: flex;
    gap: var(--spacing-md);
    margin-top: var(--spacing-sm);
    font-size: 0.95rem;
}

/* Add a bordered pill shape around each fact */
.quick-facts li {
    padding: 0.5rem 1rem;
    border: 1px solid var(--accent-gold);
    border-radius: 4px;
}

/* Constrain the main content area to a readable width */
main {
    max-width: 900px;
    margin: 0 auto;
    padding: var(--spacing-md);
}

What does this code do?

The .hero uses display: flex with flex-direction: column to stack its children vertically and center them. The gold border-bottom creates a visual separator.

The .quick-facts list also uses flexbox, but in the default row direction. This places the three facts side by side with a gap between each one. The main rule caps content width at 900px and centers it with margin: 0 auto.

  • Save style.css and refresh your browser.
  • You should see a bold gold heading ("JON "BONES" JONES" in uppercase), an italic tagline, three pill-shaped facts in a row, and a gold horizontal line separating the header from the rest of the page.

Facts stacking vertically instead of side by side?

Confirm that your .quick-facts rule has display: flex. Without it, list items default to stacking vertically. Also check that you have list-style: none to remove the bullet points.

Help me debug my flexbox hero layout.

Style the stats grid and highlights timeline

The stats section needs to display four stat cards in a horizontal row. You will use flexbox again, this time with justify-content: space-between to spread the cards evenly across the available space.

  • In style.css, add the following code below the main block:
/* Add space below the stats section */
.stats {
    margin-bottom: var(--spacing-lg);
}

/* Gold uppercase headings for both sections */
.stats h2,
.highlights h2 {
    font-family: var(--font-heading);
    font-size: 2rem;
    text-transform: uppercase;
    margin-bottom: var(--spacing-sm);
    color: var(--accent-gold);
}

/* Arrange stat cards in a row with a dark card background */
.stats-grid {
    display: flex;
    gap: var(--spacing-sm);
    justify-content: space-between;
    padding: var(--spacing-md);
    background-color: var(--bg-card);
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

/* Stack each card's number and label vertically */
.stat-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: var(--spacing-sm);
    border-radius: 8px;
}

/* Large gold numbers for impact */
.stat-number {
    font-family: var(--font-heading);
    font-size: 2.5rem;
    font-weight: 700;
    color: var(--accent-gold);
}

/* Small uppercase labels beneath each number */
.stat-label {
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 1px;
    margin-top: 0.25rem;
}

What does this code do?

The .stats-grid uses flexbox to lay out the four stat cards in a row. The justify-content: space-between pushes the cards apart evenly. The box-shadow adds a subtle drop shadow to make the card float above the background.

Each .stat-card is itself a flex column, stacking the large number on top and the label beneath it. This pattern of nesting flexbox containers is common in modern layouts.

  • Save style.css and refresh your browser.
  • You should see four stat cards arranged side by side inside a dark card with rounded corners. Each card shows a large gold number with a small label beneath it.

Stat cards stacking vertically?

Check that your .stats-grid selector matches the class name stats-grid in your HTML. A typo like .stat-grid (missing the 's') will prevent the styles from applying.

Help me figure out why my stat cards aren't in a row.

Now you will style the highlights section as a timeline with numbered circles along a gold left border.

  • In style.css, add the following code below the .stat-label block:
/* Add space below the highlights section */
.highlights {
    margin-bottom: var(--spacing-lg);
}

/* Create a vertical timeline with a gold left border */
.timeline {
    list-style: none;
    counter-reset: timeline-counter;
    padding-left: var(--spacing-md);
    border-left: 3px solid var(--accent-gold);
}

/* Space each timeline item and position for the numbered circle */
.timeline li {
    counter-increment: timeline-counter;
    padding: 0.75rem 0;
    padding-left: var(--spacing-sm);
    position: relative;
}

/* Gold circle with the item number positioned on the left border */
.timeline li::before {
    content: counter(timeline-counter);
    position: absolute;
    left: -2.25rem;
    top: 0.75rem;
    width: 1.5rem;
    height: 1.5rem;
    background-color: var(--accent-gold);
    color: var(--bg-dark);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8rem;
    font-weight: 600;
}

What does this code do?

The counter-reset and counter-increment properties create an automatic numbering system in CSS. Each li adds 1 to the counter, and the ::before pseudo-element displays that number inside a gold circle.

The position: absolute on the circle and position: relative on the li work together to place the numbered circle exactly on top of the gold left border.

  • Save style.css and refresh your browser.
  • You should see a vertical gold line on the left of the highlights section with numbered gold circles at each item. The five career milestones are listed beside the timeline.

Numbered circles appearing in the wrong spot?

Make sure .timeline li has position: relative. Without it, the absolutely positioned circles will anchor to the page instead of to their list item.

Help me fix the positioning of my timeline circles.

✔️ Awesome, I've got everything!

Great. Double check you have saved both files before moving on.

ⓧ I'd like to double check the full code

Here is the full style.css so far:

:root {
    --bg-dark: #1a1a2e;
    --bg-card: #16213e;
    --text-light: #eaeaea;
    --accent-gold: #d4af37;
    --font-heading: 'Oswald', sans-serif;
    --font-body: 'Inter', sans-serif;
    --spacing-sm: 1rem;
    --spacing-md: 2rem;
    --spacing-lg: 4rem;
}

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

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

.hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: var(--spacing-lg) var(--spacing-md);
    border-bottom: 4px solid var(--accent-gold);
}

.hero h1 {
    font-family: var(--font-heading);
    font-size: 3.5rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 2px;
    color: var(--accent-gold);
}

.tagline {
    font-size: 1.25rem;
    margin-top: 0.5rem;
    font-style: italic;
}

.quick-facts {
    list-style: none;
    display: flex;
    gap: var(--spacing-md);
    margin-top: var(--spacing-sm);
    font-size: 0.95rem;
}

.quick-facts li {
    padding: 0.5rem 1rem;
    border: 1px solid var(--accent-gold);
    border-radius: 4px;
}

main {
    max-width: 900px;
    margin: 0 auto;
    padding: var(--spacing-md);
}

.stats {
    margin-bottom: var(--spacing-lg);
}

.stats h2,
.highlights h2 {
    font-family: var(--font-heading);
    font-size: 2rem;
    text-transform: uppercase;
    margin-bottom: var(--spacing-sm);
    color: var(--accent-gold);
}

.stats-grid {
    display: flex;
    gap: var(--spacing-sm);
    justify-content: space-between;
    padding: var(--spacing-md);
    background-color: var(--bg-card);
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

.stat-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: var(--spacing-sm);
    border-radius: 8px;
}

.stat-number {
    font-family: var(--font-heading);
    font-size: 2.5rem;
    font-weight: 700;
    color: var(--accent-gold);
}

.stat-label {
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 1px;
    margin-top: 0.25rem;
}

.highlights {
    margin-bottom: var(--spacing-lg);
}

.timeline {
    list-style: none;
    counter-reset: timeline-counter;
    padding-left: var(--spacing-md);
    border-left: 3px solid var(--accent-gold);
}

.timeline li {
    counter-increment: timeline-counter;
    padding: 0.75rem 0;
    padding-left: var(--spacing-sm);
    position: relative;
}

.timeline li::before {
    content: counter(timeline-counter);
    position: absolute;
    left: -2.25rem;
    top: 0.75rem;
    width: 1.5rem;
    height: 1.5rem;
    background-color: var(--accent-gold);
    color: var(--bg-dark);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8rem;
    font-weight: 600;
}

Your page now has a dark, themed layout with bold typography and well-organized sections. Next up, you will add hover animations and polish the footer to make everything feel interactive and cohesive.

Add Visual Polish

Your page has structure, typography, and layout locked in. The stat cards sit in a row, the timeline has numbered markers, and the gold accent ties everything together.

In this step, you'll add interactivity and finishing touches. Hover effects on the stat cards give the page a sense of responsiveness, and a styled footer anchors the bottom of the page with a working link to the official UFC profile.

In this step, get ready to:
  • Add hover effects with CSS transitions to the stat cards.
  • Style the footer and link with hover animations.
Add hover effects to the stat cards

CSS transitions let you animate property changes smoothly over time. When a user hovers over an element, the browser interpolates between the original value and the new value instead of snapping instantly.

  • In style.css, find the .stat-card rule.
  • Add two new properties at the end of the rule (before the closing }) so the full .stat-card rule looks like this:
.stat-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: var(--spacing-sm);
    border-radius: 8px;
    /* Animate background and size changes over 0.3 seconds */
    transition: background-color 0.3s ease, transform 0.3s ease;
    cursor: default;
}
  • Directly below that rule, add the .stat-card:hover rule that defines what changes on hover:
.stat-card:hover {
    /* Subtle gold tint on the background */
    background-color: rgba(212, 175, 55, 0.1);
    /* Slightly enlarge the card */
    transform: scale(1.05);
}

What does this code do?

The transition property tells the browser which properties to animate and how long the animation takes. Here, 0.3s ease means a smooth 0.3-second animation that starts fast and slows down at the end.

The :hover pseudo-class only activates when the mouse is over the element. scale(1.05) enlarges the card by 5%, and the rgba background adds a faint gold wash. When the mouse leaves, both properties animate back to their original values.

  • Save style.css and refresh your browser.
  • Hover your mouse over any stat card (like the 59% Striking Accuracy card). You should see it smoothly grow slightly larger and gain a faint gold background tint.

Cards not animating on hover?

Make sure the transition property is inside the .stat-card rule, not the .stat-card:hover rule. The transition must live on the base state so the browser knows how to animate in both directions.

Also check that you have no typos in background-color inside the hover rule. A misspelled property name is silently ignored by the browser.

Why isn't my CSS hover effect working on the stat cards?

Style the footer

The footer HTML is already in place from Step 2, but without CSS it just sits as plain text. A styled footer grounds the page and gives the UFC profile link a clear visual treatment.

  • At the bottom of style.css (after the .timeline li::before rule), add the footer styles by pasting the following code:
footer {
    text-align: center;
    padding: var(--spacing-md);
    background-color: #0f0f1a;
    margin-top: var(--spacing-lg);
}

footer a {
    color: var(--accent-gold);
    text-decoration: none;
    /* Smooth transition for the underline appearing on hover */
    transition: text-decoration 0.2s ease;
}

footer a:hover {
    text-decoration: underline;
}

What does this code do?

The footer rule gives the bottom section a darker background (#0f0f1a) than the main page, visually separating it. The margin-top pushes it away from the content above.

The footer a rule styles the UFC profile link with the gold accent color and removes the default underline. On hover, the underline reappears. This is a common pattern for links: show the underline only on interaction so the link stays clean by default.

  • Save style.css and refresh your browser.
  • Scroll to the bottom of the page. You should see a darker footer section with centered text and a gold "Official UFC Profile" link.
  • Hover over the link. An underline should appear smoothly beneath the text.
  • Click the link. It should open the official UFC page for Jon Jones in a new tab.

Footer not showing a darker background?

Check that your footer rule uses background-color (not background). Also verify the color value is #0f0f1a (slightly darker than the main page color #1a1a2e). If the two colors are too similar on your monitor, try temporarily changing it to a bright color like red to confirm the rule is being applied.

Why isn't my footer styling showing up?

Why CSS transitions instead of JavaScript?

CSS transitions handle simple hover animations natively in the browser. They run on the GPU and require zero JavaScript. For hover effects, color changes, and size shifts, CSS transitions are the standard approach.

JavaScript animations are for complex sequences, user-driven interactions (like drag-and-drop), or animations that depend on data. You would reach for JavaScript when CSS alone cannot express the logic.

✔️ Awesome, I've got everything!

Great. Double check you have saved style.css before moving on.

ⓧ I'd like to double check the full code

Here is the full style.css file at this point. Compare yours against it:

:root {
    --bg-dark: #1a1a2e;
    --bg-card: #16213e;
    --text-light: #eaeaea;
    --accent-gold: #d4af37;
    --font-heading: 'Oswald', sans-serif;
    --font-body: 'Inter', sans-serif;
    --spacing-sm: 1rem;
    --spacing-md: 2rem;
    --spacing-lg: 4rem;
}

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

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

.hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: var(--spacing-lg) var(--spacing-md);
    border-bottom: 4px solid var(--accent-gold);
}

.hero h1 {
    font-family: var(--font-heading);
    font-size: 3.5rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 2px;
    color: var(--accent-gold);
}

.tagline {
    font-size: 1.25rem;
    margin-top: 0.5rem;
    font-style: italic;
}

.quick-facts {
    list-style: none;
    display: flex;
    gap: var(--spacing-md);
    margin-top: var(--spacing-sm);
    font-size: 0.95rem;
}

.quick-facts li {
    padding: 0.5rem 1rem;
    border: 1px solid var(--accent-gold);
    border-radius: 4px;
}

main {
    max-width: 900px;
    margin: 0 auto;
    padding: var(--spacing-md);
}

.stats {
    margin-bottom: var(--spacing-lg);
}

.stats h2,
.highlights h2 {
    font-family: var(--font-heading);
    font-size: 2rem;
    text-transform: uppercase;
    margin-bottom: var(--spacing-sm);
    color: var(--accent-gold);
}

.stats-grid {
    display: flex;
    gap: var(--spacing-sm);
    justify-content: space-between;
    padding: var(--spacing-md);
    background-color: var(--bg-card);
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

.stat-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: var(--spacing-sm);
    border-radius: 8px;
    transition: background-color 0.3s ease, transform 0.3s ease;
    cursor: default;
}

.stat-card:hover {
    background-color: rgba(212, 175, 55, 0.1);
    transform: scale(1.05);
}

.stat-number {
    font-family: var(--font-heading);
    font-size: 2.5rem;
    font-weight: 700;
    color: var(--accent-gold);
}

.stat-label {
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 1px;
    margin-top: 0.25rem;
}

.highlights {
    margin-bottom: var(--spacing-lg);
}

.timeline {
    list-style: none;
    counter-reset: timeline-counter;
    padding-left: var(--spacing-md);
    border-left: 3px solid var(--accent-gold);
}

.timeline li {
    counter-increment: timeline-counter;
    padding: 0.75rem 0;
    padding-left: var(--spacing-sm);
    position: relative;
}

.timeline li::before {
    content: counter(timeline-counter);
    position: absolute;
    left: -2.25rem;
    top: 0.75rem;
    width: 1.5rem;
    height: 1.5rem;
    background-color: var(--accent-gold);
    color: var(--bg-dark);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8rem;
    font-weight: 600;
}

footer {
    text-align: center;
    padding: var(--spacing-md);
    background-color: #0f0f1a;
    margin-top: var(--spacing-lg);
}

footer a {
    color: var(--accent-gold);
    text-decoration: none;
    transition: text-decoration 0.2s ease;
}

footer a:hover {
    text-decoration: underline;
}

Secret mission

Make It Responsive

Your fan page looks great on a desktop, but try shrinking the browser window. The stats cards get crushed together and the text overflows. In this mission, you'll add CSS media queries so the page adapts beautifully to any screen size.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely locally, so there are no ongoing costs. Decide whether to keep your files for future projects, or delete them entirely.

Resources you used:

  • The jon-jones-fan-page folder on your Desktop (contains index.html and style.css).

Keep everything running

No action needed. Choose this if you plan to extend this fan page with JavaScript interactivity in a future project.

  • Your jon-jones-fan-page folder stays on your Desktop. You can open it in VS Code any time to keep building.

Pause - I'll come back to this later

Close VS Code and your browser tab to free up memory. Your files remain on your Desktop for when you come back.

  • Close the VS Code window with your project open.
  • Close the browser tab showing your fan page.
  • Your jon-jones-fan-page folder is still on your Desktop whenever you want to resume.

Delete - I don't want to use this again

Remove all project files from your computer.

  • Close VS Code and the browser tab showing your fan page.
  • Delete the project folder by running this command in your terminal (macOS/Linux):
rm -rf ~/Desktop/jon-jones-fan-page

On Windows, run this in PowerShell instead:

Remove-Item -Recurse -Force ~\Desktop\jon-jones-fan-page
  • Confirm the folder is gone by checking your Desktop. You should no longer see jon-jones-fan-page listed.

Nice Work!

Nice Work!

You just built a polished single-page fan site for Jon "Bones" Jones from scratch using only HTML and CSS.

You've learned how to:

  • Structure a complete web page using semantic HTML elements (header, main, section, footer) that give your content meaning beyond just appearance.
  • Style a page with modern CSS including flexbox layout, CSS custom properties, and Google Fonts to create a cohesive dark-themed design.
  • Create interactive hover effects with CSS transitions that add interactivity without any JavaScript.
  • Secret Mission: Added responsive design with media queries so the page looks great on all screen sizes.

Ready to quiz yourself?