Build a Personal Profile Card
Build a styled profile card webpage using HTML and CSS from scratch.
Introduction
30 Second Summary
Every website you visit is built from two building blocks: HTML for the content and CSS for the look. Understanding these two languages is the first step to building anything on the web.
In this project, you will build a personal profile card from scratch using only HTML and CSS. You will start with a blank file, add your name and bio, then style it into a polished, centered card with hover animations.
What You'll Build
You will open a single HTML file in your browser and see a professional profile card with your name, a short bio, and animated social link buttons that you can show off to anyone.
By the end of this project, you'll have:
- A profile card centered on the page with your name, bio, and social links, styled with custom fonts, rounded corners, and a subtle shadow.
- Interactive hover effects on the social link buttons that smoothly animate when you move your mouse over them.
- A fully editable file where you can change any text or color and instantly see the result by refreshing your browser.
- Secret Mission: Add a dark mode toggle to your card using only CSS.
Are there any prerequisites?
None. This project starts from absolute zero. All you need is a code editor and a web browser, both of which you already have on your computer.
Before We Start
Before We Start...
Before we dive in, let's lock in what you're about to build and why it matters. Taking a moment to picture your finished profile card helps you make better decisions as you write each line of code.
Set Up Your Project Files
Every website starts with at least two files working together: an HTML file for content and a CSS file for styling. Before you can see anything in a browser, you need to create both files and connect them.
In this step, you'll create a project folder, set up your two files, and write the HTML5 boilerplate that every web page needs. By the end, you'll have a page open in your browser.
In this step, get ready to:
- Create a profile-card folder with index.html and style.css inside.
- Write the HTML5 boilerplate that connects your HTML to your CSS.
- Open your page in the browser and confirm it works.
Create your project folder and files
You need a dedicated folder to hold your project files. You'll create it on your Desktop so it's easy to find.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Terminal (macOS) or PowerShell (Windows) and press Enter to open it.
A terminal lets you create folders and files using text commands instead of clicking through menus.
- Create your project folder on the Desktop by running the commands for your operating system:
macOS
cd ~/Desktop
mkdir profile-card
cd profile-card
touch index.html style.css
Windows
cd ~/Desktop
mkdir profile-card
cd profile-card
New-Item index.html
New-Item style.css
What do these commands do?
- cd ~/Desktop moves your terminal to the Desktop folder.
- mkdir profile-card creates a new folder called profile-card.
- cd profile-card moves inside the new folder.
- touch (macOS) or New-Item (Windows) creates empty files with the names you specify.
- Confirm the files exist by running:
ls
You should see index.html and style.css in the output.
Don't see your files listed?
- Make sure you ran the commands in the correct order. If you skipped cd profile-card, you might be in the wrong folder.
- On Windows, if mkdir gave an error saying the folder already exists, just run cd profile-card and then create the files again.
- Help me figure out why my files aren't showing up in the terminal.
Now you need to open this folder in your code editor so you can edit the files.
- Switch to your code editor.
- Click File in the top menu bar.
- Click Open Folder (or Open on some editors).
- Navigate to your Desktop and select the profile-card folder, then click Open.
- In the file explorer sidebar on the left, click index.html to open it in the editor.
You should see an empty file open in a tab labelled index.html.
Add the HTML5 boilerplate
Every HTML page needs a standard set of opening tags that tell the browser how to read the file. This starting structure is called the "boilerplate."
- In index.html, paste the following code:
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Tell the browser to support special characters -->
<meta charset="UTF-8">
<!-- Make the page scale correctly on mobile -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Profile Card</title>
<!-- Connect your CSS stylesheet to this page -->
<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 page.
- The <head> section holds invisible settings that the browser needs before displaying content.
- <link rel="stylesheet" href="style.css"> connects your CSS file so any styles you write there will apply to this page.
- The <body> is where all visible page content will go. It's empty for now.
- Save index.html by pressing Cmd+S (macOS) or Ctrl+S (Windows).
Before you open this in your browser, what do you think you'll see on the page?
- Open your file in a browser by finding index.html on your Desktop inside the profile-card folder.
- Double-click index.html to open it in your default browser.
You should see a completely blank white page. Look at the browser tab at the top. It should say "Profile Card" as the page title.
Why is the page blank?
The <body> is empty, so there's nothing to display yet. The title only appears in the browser tab, not on the page itself. You'll add visible content in the next step.
Not seeing 'Profile Card' in the tab?
- Make sure you saved the file after pasting the code. Unsaved changes won't appear in the browser.
- Check that you opened index.html (not style.css) in the browser.
- Confirm the <title>Profile Card</title> line is inside the <head> section, not inside <body>.
- Help me troubleshoot why my browser tab isn't showing the right title.
✔️ Awesome, I've got everything!
Great. Make sure you've saved index.html before moving on.
ⓧ I'd like to double check the full code
Here's what your index.html should look like 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>Profile Card</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
</body>
</html>
Your style.css file should still be empty. That's expected.
Your project files are wired up and ready to go. Next up, you'll fill that empty body with your profile content and see it appear in the browser.
Build the HTML Structure
Your project files are wired up and ready. The blank white page in your browser is proof that your HTML is loading and your stylesheet is connected.
Right now that page is empty. You need to add content (your name, a bio, some links) using HTML elements so there is something visible in the browser. The result will look raw and unstyled, but it proves HTML is the skeleton that gives a page its structure.
In this step, get ready to:
- Add your profile content to the HTML file using headings, paragraphs, images, and links.
- See the raw, unstyled content appear in the browser.
Add your profile content to the page
HTML elements are the building blocks of every webpage. Each element wraps a piece of content and tells the browser what kind of content it is.
- In your code editor, switch to index.html.
- Find the empty <body> tags. Add the following code between <body> and </body>:
<div class="card">
<img src="https://i.pravatar.cc/150" alt="Profile avatar">
<h1>Your Name</h1>
<p>Frontend developer in training. Building cool things one line of code at a time.</p>
<div class="links">
<a href="#">GitHub</a>
<a href="#">LinkedIn</a>
<a href="#">Portfolio</a>
</div>
</div>
What does this code do?
- <div class="card"> creates a container (a box) for all your profile content. The class="card" gives it a name you will use later in CSS to style it.
- <img> loads a placeholder avatar image from an external URL. The alt attribute describes the image for screen readers.
- <h1> is the largest heading element. It displays your name prominently.
- <p> wraps a paragraph of text for your bio.
- <div class="links"> groups three <a> (anchor) tags together. Each anchor creates a clickable link.
Before you refresh, what do you think the page will look like? Will the content be styled and centered, or raw and plain?
- Save index.html.
- Switch to your browser and refresh the page.
You should see a round avatar image, your name as a large heading, a paragraph of bio text, and three blue underlined links. Everything is crammed to the top-left corner with no styling. It looks ugly, but it works.
Don't see any content?
- Make sure you saved index.html after pasting the code.
- Check that the code is between the opening <body> and closing </body> tags, not inside the <head>.
- Look for red highlighting in your editor. A missing > or " can break the entire page.
- My HTML page is still blank after adding code to the body. What could be wrong?
✔️ Awesome, I've got everything!
Great. Double check you have saved your file, then move on.
ⓧ I'd like to double check the full code
Here is the complete index.html file at this point. Compare yours against it:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Profile Card</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="card">
<img src="https://i.pravatar.cc/150" alt="Profile avatar">
<h1>Your Name</h1>
<p>Frontend developer in training. Building cool things one line of code at a time.</p>
<div class="links">
<a href="#">GitHub</a>
<a href="#">LinkedIn</a>
<a href="#">Portfolio</a>
</div>
</div>
</body>
</html>
Your content is in place. Next up, you will use CSS to transform this raw text into a polished, professional-looking card.
Style the Card with CSS
Your HTML content is live in the browser. You can see your name, bio, and links. But right now it looks like a plain text document from the 1990s.
CSS is what transforms raw HTML into something visually polished. In this step, you'll add colors, fonts, spacing, and shapes to make your profile card look professional.
In this step, get ready to:
- Import a custom font from Google Fonts.
- Style the card with a white background, rounded corners, and shadow.
- Make the avatar image circular and refine the card's typography.
Import a custom font and style the page background
Before you can style individual elements, you need to set up the page's foundation. That means loading a professional font and giving the page a background color that makes the card pop.
- Switch to style.css in your code editor.
- Add the Google Fonts import and body styles by copying this code into style.css:
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');
body {
margin: 0;
font-family: 'Inter', sans-serif;
background: #667eea;
color: #333;
}
What does this code do?
- @import loads the Inter font from Google's servers so you can use it on your page.
- margin: 0 removes the default whitespace browsers add around every page.
- font-family sets Inter as the typeface for all text on the page.
- background: #667eea fills the page with a purple-blue color.
- color: #333 sets a dark gray as the default text color.
- Save style.css and refresh your browser.
- The page background is now purple-blue, and your text has changed from the browser's default font to the Inter typeface.
Still seeing a white background?
- Make sure you saved style.css and not just index.html.
- Confirm the <link rel="stylesheet" href="style.css"> tag exists inside your HTML <head>. This connects the two files.
- The @import line must be the very first line of style.css with nothing above it.
Why aren't my CSS styles showing up in the browser?
Style the card container
Now that the page has a colored background, the card content blends into it. You need to give the card its own white background and shape so it stands out as a distinct element.
- Add the .card styles below your body rule by copying this code to the bottom of style.css:
.card {
background: white;
padding: 2rem;
border-radius: 1rem;
max-width: 350px;
text-align: center;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}
What does this code do?
- background: white gives the card its own color so it pops against the purple page.
- padding: 2rem adds breathing room between the card's edge and its content inside.
- border-radius: 1rem rounds the card's corners.
- max-width: 350px prevents the card from stretching too wide on large screens.
- box-shadow adds a soft shadow beneath the card, creating a floating effect.
- Save style.css and refresh your browser.
- Your card now has a white background, rounded corners, and a subtle shadow beneath it. The text is centered inside the card.
Card still looks flat with no shadow?
- Double-check that .card in your CSS matches class="card" in your HTML. The dot (.) at the start of a CSS selector means "find the element with this class name."
- Make sure there are no typos in box-shadow. It must be hyphenated.
Why isn't my .card CSS styling appearing?
Style the card's inner elements
The card container looks great, but the avatar is still a square and the text spacing feels cramped. These final styles polish each element inside the card.
- Add styles for the image, heading, paragraph, and links by copying this code to the bottom of style.css:
.card img {
border-radius: 50%;
width: 120px;
}
.card h1 {
margin: 1rem 0 0.5rem;
font-size: 1.5rem;
}
.card p {
font-size: 0.95rem;
color: #666;
line-height: 1.5;
}
.links {
margin-top: 1.5rem;
}
What does this code do?
- border-radius: 50% turns the square avatar image into a perfect circle.
- width: 120px sets a consistent size for the avatar regardless of the source image dimensions.
- The .card h1 and .card p rules fine-tune the spacing and size of your name and bio text.
- .links adds space between the bio paragraph and the link section below it.
Before you refresh, take a guess. Do you think the card will be centered on the page, or somewhere else?
- Save style.css and refresh your browser.
The card has a white background, rounded corners, a shadow, and a circular avatar. The text uses the Inter font. But the card is pinned to the top-left corner of the page, not centered.
Why is the card stuck in the corner?
By default, HTML elements stack from the top-left corner of the page. Nothing you've written so far tells the browser to place the card anywhere else. Centering something both horizontally and vertically is surprisingly tricky without a dedicated layout tool.
That's exactly the problem you'll solve in the next step.
✔️ Awesome, I've got everything!
Great. Double check you've saved style.css and your card is styled but stuck in the top-left corner.
ⓧ I'd like to double check the full code
Your style.css should contain three code chunks in this exact order. Scroll up and confirm each one is present:
- The @import line for Google Fonts, followed by the body rule (margin, font-family, background, color).
- The .card rule (background, padding, border-radius, max-width, text-align, box-shadow).
- The element rules: .card img, .card h1, .card p, and .links.
Your index.html is unchanged from the previous step.
Your card is looking sharp, but it is awkwardly stuck in the top-left corner. Next up, you'll fix that with just three lines of CSS using Flexbox.
Center the Card with Flexbox
Your card has a white background, rounded corners, a shadow, and a circular avatar. It looks professional. But there is one glaring problem: it is pinned to the top-left corner of the page.
Without Flexbox, centering something both horizontally and vertically in CSS is surprisingly painful. Flexbox solves this in three lines.
In this step, get ready to:
- Center the card horizontally and vertically using Flexbox.
- Make the layout stay centered at any browser window size.
Add Flexbox properties to your body selector
Flexbox is a CSS layout system that distributes space and aligns items in a container. By making the body a flex container, you can center everything inside it with just a few properties.
- In style.css, find your body selector.
- Add these four new properties after color: #333; so your complete body rule looks like this:
body {
margin: 0;
font-family: 'Inter', sans-serif;
background: #667eea;
color: #333;
/* Center the card on the page */
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
What do these properties do?
- display: flex turns the body into a flex container. Every direct child (your card) becomes a flex item that can be positioned.
- justify-content: center centers items horizontally (along the main axis).
- align-items: center centers items vertically (along the cross axis).
- min-height: 100vh makes the body at least as tall as the browser window. Without this, there is no vertical space to center within.
Before you refresh, what do you think will change about the card's position on the page?
- Save style.css.
- Refresh your browser.
The card is now perfectly centered both horizontally and vertically on the page. Try resizing the browser window. The card stays centered no matter the size.
Card not centering?
- Make sure you saved style.css. Unsaved changes will not show in the browser.
- Check that all four properties (display, justify-content, align-items, min-height) are inside the body { } block, not outside it or in another selector.
- If the card centers horizontally but not vertically, check that you have min-height: 100vh. Without it, the body is only as tall as the card itself, so there is no vertical space to center within.
Why isn't my card centering with Flexbox?
✔️ Awesome, I've got everything!
Great. Double check you have saved style.css and your card is centered on the page.
ⓧ I'd like to double check the full code
Your body selector in style.css should now have all of these properties (the first four are from the previous step, the last four are new):
body {
margin: 0;
font-family: 'Inter', sans-serif;
background: #667eea;
color: #333;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
All other selectors (.card, .card img, .card h1, .card p, .links) should be unchanged from the previous step.
Why Flexbox instead of margin auto?
You might have seen margin: 0 auto used to center elements. That only works horizontally and requires a fixed width.
Flexbox centers both horizontally and vertically in three lines. It also keeps the card centered when the browser window changes size, with no extra code.
Your card is now perfectly centered on a colorful background. Next up, you will turn those plain blue links into polished buttons that animate when you hover over them.
Add Hover Effects and Transitions
Your card is now perfectly centered on the page. The layout is solid, but the links are still plain blue underlined text that feel flat and unresponsive.
CSS transitions let you animate changes between states. In this step, you'll transform those plain links into styled buttons that smoothly lift and change color when you hover over them.
In this step, get ready to:
- Style the link elements as colored buttons.
- Add hover effects that animate with smooth transitions.
Style the link buttons
Right now, the three links at the bottom of your card are default browser-styled anchors. You'll turn them into proper buttons with padding, color, and rounded corners.
- In style.css, add the following rule below the .links block:
.links a {
text-decoration: none;
display: inline-block;
padding: 0.5rem 1rem;
margin: 0.25rem;
border-radius: 0.5rem;
background: #667eea;
color: white;
font-size: 0.9rem;
transition: all 0.3s ease;
}
What does this code do?
This rule targets every <a> tag inside the .links container.
- text-decoration: none removes the default blue underline that browsers put on all links.
- display: inline-block lets you add padding and margin to the links, which plain inline elements ignore.
- transition: all 0.3s ease tells the browser to animate any property change over 0.3 seconds instead of snapping instantly.
- Save style.css and refresh your browser.
- The three links now appear as purple buttons with white text and rounded corners, sitting side by side.
Still seeing blue underlined links?
- Make sure your selector is .links a (with a space between .links and a). Without the space, the browser won't match your link elements.
- Check that the new rule is placed after the closing } of the .links rule, not inside it.
- Confirm you saved the file. Unsaved changes won't show in the browser.
Why aren't my link styles showing up in the browser?
Add hover effects
The buttons look great, but they feel static. A hover state gives the user visual feedback that the buttons are interactive.
- In style.css, add this rule directly below the .links a block:
.links a:hover {
background: #4c63d2;
transform: translateY(-2px);
}
What does this code do?
The :hover pseudo-class activates only when the user's mouse is over the element.
- background: #4c63d2 switches to a darker purple, signaling that the button is active.
- transform: translateY(-2px) shifts the button 2 pixels upward, creating a subtle "lift" effect.
Because you already set transition: all 0.3s ease in the previous rule, these changes animate smoothly instead of snapping.
Before you test this, what do you think will happen when you hover over a button and then move your mouse away?
- Save style.css and refresh your browser.
- Hover over any button. It smoothly lifts up and changes to a darker purple.
- Move your mouse away. The button smoothly returns to its original position and color.
The transition works in both directions because the browser animates the change back to the default state too.
Button not lifting on hover?
- Make sure you typed :hover with a colon, not a period. .links a:hover is correct.
- Check that translateY(-2px) has a capital Y. CSS transforms are case-sensitive.
- If the color changes but there is no lift, the transform property might be misspelled. Double-check it.
Why isn't my hover effect working on the link buttons?
✔️ Awesome, I've got everything!
Great. Double-check you saved style.css and your hover effects are working smoothly.
ⓧ I'd like to double check the full code
Your style.css should now contain all the rules from earlier steps, plus these two new blocks at the bottom, in this order:
- The .links a rule with text-decoration: none, display: inline-block, padding, margin, border-radius, background, color, font-size, and transition: all 0.3s ease.
- The .links a:hover rule with background: #4c63d2 and transform: translateY(-2px).
Scroll up to the code blocks in this step and confirm yours matches exactly. The index.html file has not changed in this step.
Your profile card is complete. You started with a blank page, structured content with HTML, styled it with CSS, centered it with Flexbox, and now added interactive hover effects with transitions. That is the full front-end fundamentals loop.
Secret mission
Add a CSS-Only Dark Mode Toggle
Real websites support dark mode. Can you build a toggle that switches the entire page to a dark color scheme using only CSS? No JavaScript allowed.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs entirely locally, so there are no ongoing costs.
Resources you used:
- The profile-card folder on your Desktop containing index.html and style.css.
Keep everything running
No action needed. Choose this if you want to keep editing your profile card or use it as a reference for future projects.
- Your profile-card folder stays on your Desktop. You can open index.html in your browser anytime to see your card.
- The files take up less than a few kilobytes of storage, so there is no practical reason to delete them.
Pause - I'll come back to this later
Since this project is just local files, there is nothing to pause. Your files sit on disk and use no memory or processing power when you are not editing them.
- Close the index.html and style.css tabs in your code editor.
- Close the browser tab showing your profile card.
- When you want to return, open index.html in your browser and both files in your code editor.
Delete - I don't want to use this again
Remove all project files from your computer.
- Close any open tabs for index.html and style.css in your code editor and browser.
- Delete the profile-card folder by running this command in your terminal:
macOS
rm -rf ~/Desktop/profile-card
Windows
rmdir /s /q %USERPROFILE%\Desktop\profile-card
- Confirm deletion by running ls ~/Desktop (macOS) or dir %USERPROFILE%\Desktop (Windows). The profile-card folder should no longer appear.
That's a Wrap!
That's a Wrap!
Nice work! You just built a polished personal profile card from an empty file to a fully styled, interactive webpage.
You've learned how to:
- Build a complete HTML page from scratch with proper document structure, meta tags, and a linked stylesheet.
- Style elements using CSS properties for color, spacing, typography, and shape, then center a card on the page using Flexbox.
- Add interactive hover effects with CSS transitions and transforms that make elements respond smoothly to user interaction.
- Secret Mission: Implemented a dark mode toggle using only CSS and the :has() selector, proving that CSS alone can handle interactive state changes.
Ready to quiz yourself?