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
  • WorkoutCard component aangemaakt
  • Workouts in een grid getoond
  • App ziet er verzorgd uit

Volgende Stap

App ziet er goed uit! Laatste stap: live zetten op Vercel.

Deployment →

Zet je Workout Tracker live op Vercel