Goal
Create Skills: a responsive card grid that lists your skills by category.
Skills.jsx
function Skills() {
return (
<section id="skills" className="bg-white py-20 dark:bg-slate-900">
<div className="mx-auto max-w-5xl px-6">
<h2 className="mb-2 text-3xl font-bold text-slate-900 dark:text-slate-100">
Skills
</h2>
<p className="mb-10 max-w-2xl text-slate-600 dark:text-slate-400">
Tools I use to design, build, and ship full stack applications.
</p>
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
{[
{
title: "Frontend",
items: "HTML, CSS, JavaScript, React, Tailwind CSS",
},
{
title: "Backend",
items: "Node.js, Express, REST APIs, authentication",
},
{
title: "Data",
items: "SQL, MongoDB, Prisma, data modeling",
},
{
title: "Tooling",
items: "Git, Vite, npm, ESLint, VS Code",
},
{
title: "Soft skills",
items: "Communication, debugging, pair programming",
},
{
title: "Currently learning",
items: "TypeScript, testing, cloud deployment",
},
].map((skill) => (
<article
key={skill.title}
className="rounded-2xl border border-slate-200 bg-white p-6 shadow-sm dark:border-slate-700 dark:bg-slate-900"
>
<h3 className="mb-2 text-lg font-semibold text-slate-900 dark:text-slate-100">
{skill.title}
</h3>
<p className="text-sm leading-relaxed text-slate-600 dark:text-slate-400">
{skill.items}
</p>
</article>
))}
</div>
</div>
</section>
);
}
export default Skills;
Edit the skill groups so they match what you actually know.
Tailwind chunks explained: section chrome
| Class | Meaning |
|---|---|
id="skills" |
Target for #skills nav links |
bg-white / dark:bg-slate-900 |
Alternate band vs the surface-colored hero |
py-20 |
Tall section padding |
mx-auto max-w-5xl px-6 |
Same content rail as Hero and Navbar |
mb-2 / mb-10 |
Tight heading gap, then space before the grid |
max-w-2xl |
Keep the intro paragraph from stretching too wide |
text-3xl font-bold |
Section heading scale |
Tailwind chunks explained: responsive grid
| Class | Meaning |
|---|---|
grid |
CSS Grid container |
grid-cols-1 |
One column by default (phones) |
sm:grid-cols-2 |
Two columns from sm (640px) up |
lg:grid-cols-3 |
Three columns from lg (1024px) up |
gap-6 |
Consistent gap between cards |
Mental model: write the mobile layout first, then add breakpoint prefixes for larger screens.
Tailwind chunks explained: skill cards
| Class | Meaning |
|---|---|
rounded-2xl |
Large corner radius for a soft card |
border |
Visible edge |
border-slate-200 / dark:border-slate-700 |
Theme-aware outline |
bg-white / dark:bg-slate-900 |
Card surface |
p-6 |
Inner padding |
shadow-sm |
Light elevation |
text-lg font-semibold |
Card title weight |
text-sm leading-relaxed |
Comfortable description type |
Wire into App.jsx
import Navbar from "./components/Navbar";
import Hero from "./components/Hero";
import Skills from "./components/Skills";
function App() {
return (
<div className="min-h-screen bg-surface font-sans text-ink antialiased dark:bg-slate-950 dark:text-slate-100">
<Navbar />
<main>
<Hero />
<Skills />
</main>
</div>
);
}
export default App;
Check
- 1 column on a narrow phone width
- 2 columns around tablet width
- 3 columns on a wide desktop
- Cards stay readable in dark mode
- Navbar Skills jumps to this section
Next: build the Projects cards with hover motion.