Uitleg — Styling opties
Next.js ondersteunt meerdere manieren van stylen. We behandelen de twee meest gebruikte:
| Methode | Wanneer gebruiken |
|---|---|
| Tailwind CSS | Snel stylen met utility classes direct in JSX |
| CSS Modules | Component-specifieke CSS zonder conflicten |
💡 Welke kiezen?
Heb je Tailwind gekozen tijdens installatie? Gebruik Tailwind. Anders is CSS Modules een goede keuze. Je kunt ook beide combineren!
Uitleg — Tailwind CSS
Tailwind laat je stylen met kant-en-klare klasse-namen direct in je JSX. Geen aparte CSS bestanden nodig.
// Zonder Tailwind
<button style={{ backgroundColor: 'blue', color: 'white', padding: '8px 16px' }}>
Toevoegen
</button>
// Met Tailwind
<button className="bg-blue-500 text-white px-4 py-2 rounded">
Toevoegen
</button>
Veelgebruikte Tailwind classes
// Layout
className="flex" // display: flex
className="flex-col" // flex-direction: column
className="gap-4" // gap: 1rem
className="p-4" // padding: 1rem
className="px-4 py-2" // padding horizontaal / verticaal
className="mt-4 mb-8" // margin top / bottom
className="w-full" // width: 100%
className="max-w-2xl" // max-width: 42rem
// Tekst
className="text-xl" // font-size: 1.25rem
className="font-bold" // font-weight: bold
className="text-gray-500" // grijze tekstkleur
// Achtergrond & randen
className="bg-white" // witte achtergrond
className="rounded-lg" // afgeronde hoeken
className="border" // rand
// Hover effecten
className="hover:bg-blue-600" // donkerder blauw bij hover
className="cursor-pointer" // handje cursor
Workout kaartje met Tailwind
function WorkoutCard({ workout }) {
return (
<div className="bg-white rounded-lg shadow p-4 border border-gray-200">
<h3 className="text-lg font-bold text-gray-800">{workout.title}</h3>
<p className="text-gray-500 text-sm mt-1">
{workout.reps} reps @ {workout.load}kg
</p>
</div>
);
}
Uitleg — CSS Modules
CSS Modules zijn gewone CSS bestanden met de extensie .module.css. De klassen worden automatisch uniek gemaakt, zodat ze nooit conflicteren tussen componenten.
Aanmaken
app/components/WorkoutCard.module.css
/* WorkoutCard.module.css */
.card {
background: white;
border-radius: 8px;
padding: 16px;
border: 1px solid #e5e7eb;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.title {
font-size: 1.125rem;
font-weight: bold;
color: #1f2937;
}
.info {
color: #6b7280;
font-size: 0.875rem;
margin-top: 4px;
}
Gebruiken
// WorkoutCard.js
import styles from './WorkoutCard.module.css';
export default function WorkoutCard({ workout }) {
return (
<div className={styles.card}>
<h3 className={styles.title}>{workout.title}</h3>
<p className={styles.info}>
{workout.reps} reps @ {workout.load}kg
</p>
</div>
);
}
💡 Voordeel van CSS Modules
Twee componenten kunnen allebei een class .title hebben zonder conflict. Next.js maakt ze automatisch uniek: .WorkoutCard_title__abc123.
Stap 1 — Style de navigatiebalk in layout.js
Vervang de inhoud van app/layout.js met:
// app/layout.js
import './globals.css';
import Link from 'next/link';
export const metadata = {
title: 'Workout Tracker',
description: 'Bijhouden van je workouts',
};
export default function RootLayout({ children }) {
return (
<html lang="nl">
<body className="bg-gray-100 min-h-screen">
<nav className="bg-white shadow-sm border-b border-gray-200">
<div className="max-w-4xl mx-auto px-4 py-3 flex gap-6">
<Link
href="/"
className="font-bold text-blue-600 text-lg"
>
💪 Workout Tracker
</Link>
<Link
href="/workouts"
className="text-gray-600 hover:text-blue-600 transition-colors"
>
Workouts
</Link>
</div>
</nav>
<main className="max-w-4xl mx-auto px-4 py-8">
{children}
</main>
</body>
</html>
);
}
Stap 2 — Maak een WorkoutCard component aan
Maak een nieuw bestand app/components/WorkoutCard.js aan:
// app/components/WorkoutCard.js
import Link from 'next/link';
export default function WorkoutCard({ workout }) {
return (
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-5 hover:shadow-md transition-shadow">
<Link href={`/workouts/${workout._id}`}>
<h3 className="text-lg font-semibold text-gray-900 hover:text-blue-600">
{workout.title}
</h3>
</Link>
<div className="flex gap-4 mt-2 text-sm text-gray-500">
<span>🔁 {workout.reps} reps</span>
<span>🏋️ {workout.load}kg</span>
</div>
</div>
);
}
Stap 3 — Update de overzichtspagina
Vervang de inhoud van app/workouts/page.js om WorkoutCard te gebruiken:
// app/workouts/page.js
import WorkoutCard from '../components/WorkoutCard';
import AddWorkoutForm from '../components/AddWorkoutForm';
// ... getWorkouts functie ...
export default async function WorkoutsPage() {
const workouts = await getWorkouts();
return (
<div>
<h1 className="text-3xl font-bold text-gray-900 mb-6">Mijn Workouts</h1>
<AddWorkoutForm />
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mt-6">
{workouts.map((workout) => (
<WorkoutCard key={workout._id} workout={workout} />
))}
</div>
</div>
);
}
Uitleg — next/image
Voor afbeeldingen gebruik je de Image component van Next.js. Die optimaliseert afbeeldingen automatisch (grootte, formaat, lazy loading).
import Image from 'next/image';
// In je component:
<Image
src="/logo.png"
alt="Workout Tracker logo"
width={200}
height={60}
/>
💡 Waarom next/image?
Gewone <img> laadt altijd de volledige afbeelding. next/image converteert automatisch naar WebP, schaalt af naar het juiste formaat en laadt alleen wat zichtbaar is.
Checklist
✅ Check of je hebt:
- Navigatiebalk gestyled in
layout.js WorkoutCardcomponent aangemaakt- Workouts in een grid getoond
- App ziet er verzorgd uit
Volgende Stap
App ziet er goed uit! Laatste stap: live zetten op Vercel.
Zet je Workout Tracker live op Vercel