Building a Responsive Card Component From Scratch
· 4 min read
This is lesson seventeen, and you now have every individual tool you need.
This is lesson seventeen, and you now have every individual tool you need: the box model, selectors, flexbox and grid, positioning, variables, transitions, responsive breakpoints, and cascade awareness. This lesson is a deliberate change of pace: instead of introducing something new, it walks through building one complete, realistic component from a blank page, combining everything, the way you'd actually approach a real task.
The goal: a responsive profile card for Tony Stark that looks good on both phone and desktop, with a hover effect, built with clean, reusable CSS.
The HTML Structure
Start with the HTML structure, written plainly, with no styling decisions baked in yet.
<div class="profile-card">
<img src="tony-stark.jpg" alt="Tony Stark" class="profile-avatar">
<div class="profile-info">
<h2 class="profile-name">Tony Stark</h2>
<p class="profile-role">Engineer & Inventor</p>
<p class="profile-bio">Builds suits. Occasionally saves the world. Also known as Iron Man.</p>
<a href="#" class="profile-button">View Profile</a>
</div>
</div>
Notice the structure follows lesson two's naming advice: classes describe what things ARE (profile-avatar, profile-role), not how they currently look.
Project Wide Foundation
Next, set up the project-wide foundation first, following lesson twelve's variable habit and lesson sixteen's reset habit, before touching the card itself.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--color-text: #1e293b;
--color-muted: #64748b;
--color-primary: #2563eb;
--radius-md: 12px;
--spacing-md: 16px;
}
body {
font-family: "Helvetica Neue", Arial, sans-serif;
line-height: 1.5;
color: var(--color-text);
}
Building The Mobile Layout
Now build the card itself, starting mobile-first (lesson fifteen): a simple stacked layout, image on top, text below, which is naturally what a narrow phone screen needs.
.profile-card {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
background: white;
border-radius: var(--radius-md);
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
padding: var(--spacing-md);
max-width: 320px;
margin: 0 auto;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.profile-card:hover {
transform: translateY(-4px);
box-shadow: 0 10px 24px rgba(0,0,0,0.12);
}
.profile-avatar {
width: 96px;
height: 96px;
border-radius: 50%;
object-fit: cover;
margin-bottom: var(--spacing-md);
}
.profile-name {
font-size: 1.25rem;
margin-bottom: 4px;
}
.profile-role {
color: var(--color-muted);
font-size: 0.9rem;
margin-bottom: 12px;
}
.profile-bio {
font-size: 0.95rem;
margin-bottom: var(--spacing-md);
}
.profile-button {
display: inline-block;
background: var(--color-primary);
color: white;
text-decoration: none;
padding: 10px 20px;
border-radius: 6px;
transition: background-color 0.2s ease;
}
.profile-button:hover {
background-color: #1e40af;
}
Every piece here is a direct callback to an earlier lesson: flexbox column layout for stacking (lesson eight), a circular avatar with object-fit (lesson six), rem and px chosen deliberately per the sizing lesson, variables for color and spacing (lesson twelve), a card-lift hover transition (lesson fourteen), and max-width with margin: 0 auto to center and cap the card's width on any screen, a combination mentioned back in lesson four.
Adapting For Wider Screens
Now, make it adapt at wider screens, mobile-first, using min-width. On a tablet or desktop, switching the card to a horizontal layout (image beside the text instead of above it) often makes better use of the extra width.
@media (min-width: 600px) {
.profile-card {
flex-direction: row;
text-align: left;
max-width: 480px;
gap: var(--spacing-md);
}
.profile-avatar {
margin-bottom: 0;
flex-shrink: 0;
}
}
flex-shrink: 0 on the avatar is a small but important detail: without it, if the text content is long, the flex container could shrink the avatar's width to make room, distorting the circular image. Setting flex-shrink: 0 tells the browser the avatar's size is fixed and non-negotiable, and only the text content should flex to fill remaining space.
Practical Tips And Accessibility
This entire exercise demonstrates something important about real CSS work: a polished-feeling component is rarely one exotic trick, it's a dozen ordinary techniques from basic lessons, applied together thoughtfully and consistently. Professional-looking CSS is less about knowing secret properties and more about combining fundamentals carefully.
If you look back across every property used in this one card, it's worth noticing none of it was new. That's intentional: the point of this lesson is proving that eighteen short, focused lessons can combine into something that feels genuinely finished and professional, as long as each individual piece is solid. A beginner who rushes through many lessons without practicing often struggles to combine them later; a beginner who builds a few complete components like this one usually finds the combining step comes naturally, because the fundamentals were never shaky to begin with.
Practical tip: when building any new component, follow this same order: write plain HTML structure first with no styling, apply a reset and variables, build the simplest mobile layout, add visual polish (shadow, radius, color), then add a hover/transition layer, and only at the end, layer in responsive adjustments for wider screens. Building in this order avoids fighting your own CSS halfway through.
One last refinement worth adding: a small focus style on the button, so the card remains fully usable for someone navigating by keyboard, a habit the very last lesson of this course will insist on more generally.
.profile-button:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 3px;
}
Adding this one rule now, while the component is still fresh in your mind, is far easier than retrofitting accessibility onto dozens of components later in a real project.
Your turn: build this exact card for Tony Stark as written above, then duplicate it to build a second card for Vikesh Singh with different bio text, confirming your CSS classes are reusable and the second card automatically inherits the same polished styling without copying any new rules.
KEEP READING