What you'll build
<article class="card">
<img src="https://api.dicebear.com/7.x/thumbs/svg?seed=Nova" alt="Cartoon avatar of Nova" width="110" height="110">
<h1>Nova Okafor</h1>
<p class="role">Frontend Developer</p>
<p>I turn coffee and curiosity into friendly websites.</p>
<ul class="skills">
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
<div class="actions">
<a href="#">Portfolio</a>
<a href="#">Contact</a>
</div>
</article>body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
background: #fbf7f0;
font-family: system-ui, sans-serif;
}
.card {
width: min(320px, 90vw);
padding: 28px;
text-align: center;
background: white;
border: 2px solid #15161b;
border-radius: 20px;
box-shadow: 6px 6px 0 #15161b;
}
.card img {
width: 110px;
height: 110px;
margin: 0 auto;
border-radius: 50%;
border: 3px solid #17a865;
background: #d6f4e4;
}
.card h1 {
margin: 14px 0 2px;
font-size: 1.5rem;
}
.role {
margin: 0 0 12px;
color: #17a865;
font-weight: 700;
}
.skills {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 8px;
padding: 0;
list-style: none;
}
.skills li {
padding: 4px 12px;
border-radius: 999px;
background: #fff1c2;
font-size: 0.85rem;
font-weight: 600;
}
.actions {
display: flex;
gap: 10px;
margin-top: 18px;
}
.actions a {
flex: 1;
padding: 10px;
border-radius: 12px;
border: 2px solid #15161b;
color: #15161b;
text-decoration: none;
font-weight: 700;
}
.actions a:first-child {
background: #15161b;
color: white;
}You'll build the kind of profile card you see on team pages and social sites: a round photo, a name, a short bio, a row of skill tags and a couple of buttons.
It's an ideal first project because it uses the HTML you already know (headings, paragraphs, images, lists and links) and teaches the CSS that makes things look designed: spacing, borders, rounded corners, shadows and flexbox.
Plan the card before you write code
Every good layout starts with a quick plan. Look at a profile card on any team page and you'll see the same pieces stacked from top to bottom: a photo, a name, a job title, a short paragraph about the person, a few skills and a couple of links. Write those pieces down in order and you already have your HTML.
The trick is to write all the HTML first and style it afterwards. With no CSS at all, your card should still make sense: the heading should read as a heading, the skills should read as a list and the links should work. If the content is solid without styling, the CSS has only one job, which is making it look good. This habit also makes your page easier for screen readers and search engines to understand.
Here's how each part maps to an HTML element:
| Part of the card | Element | Why this element |
|---|---|---|
| The whole card | <article> | It's a self-contained piece of content |
| Photo | <img> with alt | Images need a text alternative |
| Name | <h1> or <h2> | It's the title of the card |
| Job title and bio | <p> | Ordinary text |
| Skills | <ul> with <li> | It's a list of short items |
| Social links | <a> | They take the visitor somewhere |
If any of these feel unfamiliar, the HTML images, HTML lists and HTML links lessons cover them in a few minutes each.
The CSS ideas you'll use
Four CSS ideas do almost all the work in this project:
- The box model. Every element is a box with content, padding, a border and margin. Padding adds space inside the card, margin pushes things apart. The box model lesson explains it with diagrams.
- border-radius. One property turns square corners into soft ones, and
border-radius: 50%turns a square photo into a perfect circle. - box-shadow. A soft shadow lifts the card off the page so it looks like something you could pick up.
- Flexbox.
display: flexon the body centres the card, and on the skills list it lines the tags up in a row that wraps on small screens. See the flexbox lesson for every option.
Make the card responsive and add a hover effect
A profile card has to look right on a 6-inch phone and a 27-inch monitor. The card in this project already uses min(320px, 90vw), so it never grows wider than 320 pixels and never overflows a small screen. That one function replaces a media query and is the simplest way to make a responsive card in CSS.
A subtle hover effect makes the card feel interactive. Lift it a few pixels and deepen the shadow, and use a transition so the movement is smooth:
.card { transition: transform 0.2s ease, box-shadow 0.2s ease; }
.card:hover { transform: translateY(-4px); box-shadow: 10px 10px 0 #15161b; }
@media (prefers-reduced-motion: reduce) {
.card { transition: none; }
}The prefers-reduced-motion query switches the animation off for visitors who have asked their operating system for less motion. It's a small detail that separates a careful build from a rushed one. The CSS transitions lesson explains timing and easing, and the responsive design lesson shows more ways to adapt a layout to any screen.
Requirements checklist
- A round profile image with meaningful
alttext - The person's name as a heading and their job title underneath
- A short bio paragraph
- At least three skills shown as "tags" in a row
- Two links styled as buttons
- The card is centred on the page and looks good on a phone
Starter code
Press Run to see where you're starting from, then follow the steps.
<article class="card">
<img src="https://api.dicebear.com/7.x/thumbs/svg?seed=Nova" alt="Cartoon avatar of Nova">
<h1>Nova Okafor</h1>
<p>Frontend Developer</p>
<p>I turn coffee and curiosity into friendly websites.</p>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
<a href="#">Portfolio</a>
<a href="#">Contact</a>
</article>/* Your styles go here */
Step-by-step guide
- 1
Centre the card on the page
Give the page a soft background and use grid on the
bodyto put the card in the middle, both horizontally and vertically.CSS body { margin: 0; min-height: 100vh; display: grid; place-items: center; background: #fbf7f0; font-family: system-ui, sans-serif; }min-height: 100vhmakes the body at least as tall as the screen, so there's room to centre vertically. - 2
Turn the article into a card
Give it a fixed width, padding, a border, rounded corners and a solid "offset" shadow.
CSS .card { width: min(320px, 90vw); padding: 28px; text-align: center; background: white; border: 2px solid #15161b; border-radius: 20px; box-shadow: 6px 6px 0 #15161b; }min(320px, 90vw)means "320px, unless the screen is narrower, in which case 90% of its width". That one line makes the card work on phones. - 3
Make the photo round
CSS .card img { width: 110px; height: 110px; border-radius: 50%; border: 3px solid #17a865; background: #d6f4e4; }A
border-radiusof50%on a square image turns it into a perfect circle. - 4
Style the name and job title
Add a class to the job title in your HTML first:
<p class="role">Frontend Developer</p>. Then:CSS .card h1 { margin: 14px 0 2px; font-size: 1.5rem; } .role { margin: 0 0 12px; color: #17a865; font-weight: 700; } - 5
Turn the list into skill tags
Add
class="skills"to the<ul>. Flexbox lays the items out in a row andgapspaces them.CSS .skills { display: flex; justify-content: center; flex-wrap: wrap; gap: 8px; padding: 0; list-style: none; } .skills li { padding: 4px 12px; border-radius: 999px; background: #fff1c2; font-size: 0.85rem; font-weight: 600; } - 6
Style the links as buttons
Wrap the two links in
<div class="actions">…</div>and add:CSS .actions { display: flex; gap: 10px; margin-top: 18px; } .actions a { flex: 1; padding: 10px; border-radius: 12px; border: 2px solid #15161b; color: #15161b; text-decoration: none; font-weight: 700; } .actions a:first-child { background: #15161b; color: white; }flex: 1makes both buttons share the space equally.
Final solution
Show the complete solution
<article class="card">
<img src="https://api.dicebear.com/7.x/thumbs/svg?seed=Nova" alt="Cartoon avatar of Nova" width="110" height="110">
<h1>Nova Okafor</h1>
<p class="role">Frontend Developer</p>
<p>I turn coffee and curiosity into friendly websites.</p>
<ul class="skills">
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
<div class="actions">
<a href="#">Portfolio</a>
<a href="#">Contact</a>
</div>
</article>body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
background: #fbf7f0;
font-family: system-ui, sans-serif;
}
.card {
width: min(320px, 90vw);
padding: 28px;
text-align: center;
background: white;
border: 2px solid #15161b;
border-radius: 20px;
box-shadow: 6px 6px 0 #15161b;
}
.card img {
width: 110px;
height: 110px;
margin: 0 auto;
border-radius: 50%;
border: 3px solid #17a865;
background: #d6f4e4;
}
.card h1 {
margin: 14px 0 2px;
font-size: 1.5rem;
}
.role {
margin: 0 0 12px;
color: #17a865;
font-weight: 700;
}
.skills {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 8px;
padding: 0;
list-style: none;
}
.skills li {
padding: 4px 12px;
border-radius: 999px;
background: #fff1c2;
font-size: 0.85rem;
font-weight: 600;
}
.actions {
display: flex;
gap: 10px;
margin-top: 18px;
}
.actions a {
flex: 1;
padding: 10px;
border-radius: 12px;
border: 2px solid #15161b;
color: #15161b;
text-decoration: none;
font-weight: 700;
}
.actions a:first-child {
background: #15161b;
color: white;
}Bonus challenges
- Add a hover effect that lifts the card slightly using
transform: translateY(-4px)and a CSS transition. - Add a dark version of the card using CSS variables.
- Make three cards for a "Meet the team" section and lay them out with CSS Grid.
Common mistakes and how to fix them
The photo looks squashed or stretched. This happens when the image isn't square but you give it the same width and height. Add object-fit: cover to the img rule. The browser then crops the photo to fill the circle instead of distorting it.
The card touches the edges on a phone. You probably set width: 400px. Use max-width: 360px and width: 100% instead, plus some padding on the body. The card can then shrink on small screens but never grows too wide.
The skill tags still have bullets and indentation. Lists come with default styles. Remove them with list-style: none; padding: 0; margin: 0; on the ul.
The buttons are different sizes. Links are inline elements, so padding behaves oddly until you change their display. Give them display: inline-block (or put them in a flex container) and the same padding.
Check your work
Before you call the project finished, test it the way a real visitor would:
- Resize the window from wide to narrow. The card should stay centred and readable at every width.
- Press Tab to move through the page. Each link should show a visible focus outline so keyboard users know where they are.
- Break the image path for a moment by misspelling the file name. The
alttext should still describe the person. - Zoom to 200%. Nothing should overlap or get cut off.
If all four pass, you've built something many professional pages get wrong.
Where you'll use this card design
The pattern you just built appears all over the web, so it's worth knowing well. Team pages show a grid of profile cards, one per person. Author boxes sit at the end of blog posts with a photo, a short bio and links. Portfolio sites often open with a large version of the card as a personal introduction, and link-in-bio pages are essentially a profile card with a longer list of buttons.
Each of these is the same HTML with small CSS changes. Put three or four cards inside a container with display: grid and grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)), and you have a responsive team section that goes from one column on phones to four on desktops with no media queries. Building one card properly first, then reusing it, is exactly how professional developers work with components.
Questions beginners ask
Can I use my own photo? Yes. Put the image file next to your HTML file and change the src to its name, for example src="me.jpg". The file paths lesson explains how to point at images in other folders.
Should the name be an h1 or an h2? If the card is the only thing on the page, use <h1>. If it sits on a page with other cards, the page title is the <h1> and each card's name is an <h2>.
How do I put this online? Push the folder to a GitHub repository and switch on GitHub Pages. Your card gets its own web address that you can share or add to a CV.