Building a Portfolio Website
Planning Your Portfolio
A strong portfolio website is your most powerful job-seeking tool as a developer. Before writing a single line of code, plan the sections you need:
- Hero — your name, role, and a call-to-action button
- About — a brief summary of who you are and your background
- Skills — technologies you know
- Projects — 3-5 projects with live links and GitHub links
- Contact — a form or your contact details
Breaking Down the UI into Components
Component thinking is the core React skill. Identify reusable pieces:
PortfolioApp
├── Navbar
├── HeroSection
│ ├── HeroText
│ └── HeroImage
├── AboutSection
├── SkillsSection
│ └── SkillTag (repeated)
├── ProjectsSection
│ └── ProjectCard (repeated)
├── ContactSection
│ └── ContactForm
└── Footer
CSS Modules
CSS Modules scope styles to a single component, preventing class name collisions. Create a .module.css file alongside your component:
/* ProjectCard.module.css */
.card {
background: white;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
transition: transform 0.2s, box-shadow 0.2s;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}
.image { width: 100%; height: 200px; object-fit: cover; }
.content { padding: 20px; }
.title { font-size: 1.1rem; font-weight: 700; color: #111827; margin: 0 0 8px; }
.description { color: #6B7280; font-size: 0.9rem; line-height: 1.6; }
.links { display: flex; gap: 12px; margin-top: 16px; }
.link { font-size: 0.85rem; font-weight: 600; text-decoration: none; color: #42BCB1; }
// ProjectCard.jsx
import styles from "./ProjectCard.module.css";
function ProjectCard({ title, description, imageUrl, liveUrl, githubUrl, tags }) {
return (
<article className={styles.card}>
<img src={imageUrl} alt={title} className={styles.image} />
<div className={styles.content}>
<h3 className={styles.title}>{title}</h3>
<p className={styles.description}>{description}</p>
<div className={styles.links}>
<a href={liveUrl} target="_blank" rel="noopener noreferrer" className={styles.link}>
Live Demo
</a>
<a href={githubUrl} target="_blank" rel="noopener noreferrer" className={styles.link}>
GitHub
</a>
</div>
</div>
</article>
);
}
export default ProjectCard;
Responsive Layout with CSS Grid and Flexbox
Use CSS Grid for the projects section layout:
/* ProjectsSection.module.css */
.section {
padding: 80px 24px;
max-width: 1100px;
margin: 0 auto;
}
.heading {
text-align: center;
font-size: 2rem;
margin-bottom: 48px;
color: #111827;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 24px;
}
repeat(auto-fit, minmax(300px, 1fr)) automatically creates as many columns as fit, each at least 300px wide. This is responsive without a single media query.
Animations with CSS Transitions
Add smooth interactions using CSS transitions and the :hover pseudo-class:
/* Fade in on page load with @keyframes */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(24px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.hero-text {
animation: fadeInUp 0.6s ease-out both;
}
.hero-cta {
animation: fadeInUp 0.6s ease-out 0.2s both; /* 200ms delay */
}
Accessibility Best Practices
A professional portfolio must be accessible:
// Use semantic HTML elements
<header>...</header>
<main>...</main>
<section aria-label="Projects">...</section>
<footer>...</footer>
// Always provide alt text for images
<img src={project.image} alt={"Screenshot of " + project.title} />
// Use aria-label for icon-only buttons
<button aria-label="Open menu"><MenuIcon /></button>
// Ensure links describe their destination
<a href="/contact">Get in touch</a> // Good
<a href="/contact">Click here</a> // Avoid — not descriptive
Key Takeaways
- Plan your portfolio sections before writing code: Hero, About, Skills, Projects, Contact
- Break the UI into components and identify which ones are reusable (ProjectCard, SkillTag) vs one-off (HeroSection)
- CSS Modules scope styles to individual components, preventing class name collisions in large codebases
- CSS Grid with repeat(auto-fit, minmax(300px, 1fr)) creates responsive layouts without media queries
- CSS transitions and keyframe animations add polish without JavaScript
- Use semantic HTML elements and descriptive alt text to ensure your portfolio is accessible
Practice Exercise
- Build a
HeroSectioncomponent with your name, a short tagline, and a "View Projects" button - Build a
ProjectCardcomponent using CSS Modules as shown in this lesson - Create a
ProjectsSectionthat renders 3ProjectCardcomponents with different data - Add a hover lift effect to
ProjectCardusing CSS transitions - Ensure all images have descriptive alt text and all links describe their destination
Try it yourself
Key Takeaways
- Plan portfolio sections before coding: Hero, About, Skills, Projects, and Contact
- Component thinking means identifying reusable pieces (ProjectCard, SkillTag) and one-off sections (HeroSection)
- CSS Modules scope styles to a component by transforming class names to unique identifiers at build time
- CSS Grid with repeat(auto-fit, minmax(300px, 1fr)) creates a responsive card grid without media queries
- CSS transitions (transition: transform 0.25s ease) add smooth hover effects without JavaScript
- Semantic HTML and descriptive alt text and link text are non-negotiable for an accessible, professional portfolio
Quick Quiz
1.What problem do CSS Modules solve?
2.What does repeat(auto-fit, minmax(300px, 1fr)) do in CSS Grid?
3.Why should link text be descriptive rather than 'Click here'?
4.What is the rel='noopener noreferrer' attribute on external links used for?
Ready to go further?
CareerEx gives you structured 12-week training, live classes every Saturday and Sunday, real tutor feedback, and a certificate. Join the next cohort.
Join CareerEx