Tilbake til bloggen
Guide2. mars 2026

Tailwind CSS: Utility-first i praksis — ikke bare klassenavn

Da jeg først så Tailwind CSS, var reaksjonen den samme som de fleste: "Hvorfor skal jeg skrive klassenavn som ser ut som inline styles?" Etter å ha brukt BEM-konvensjoner, CSS Modules og til og med styled-components, føltes det som et steg bakover. Men etter å ha bygd to komplette prosjekter med Tailwind — denne porteføljen og Tuli sin frontend — har jeg endret mening fullstendig.

Tailwind er ikke bare klassenavn. Det er et designsystem som bor i koden, og det har fundamentalt endret hvordan jeg jobber med frontend.

Hvorfor utility-first slår alt annet for meg

Problemet med tradisjonell CSS — BEM, CSS Modules, eller til og med styled-components — er at du alltid ender opp med å ta to beslutninger: hva skal komponenten se ut som, og hva skal CSS-klassen hete? Det høres trivielt ut, men over tid blir navngivning en konstant kognitiv belastning. .card-header__title--highlighted eller .card-title-highlight? Det spiller ingen rolle — begge er vilkårlige.

Med Tailwind forsvinner navngivningsproblemet. Stilen er direkte i komponentkoden. Når jeg ser <div className="rounded-2xl bg-white/10 backdrop-blur-xl border border-white/20 p-6">, vet jeg nøyaktig hva elementet ser ut som uten å åpne en CSS-fil.

Men den virkelige gevinsten er konsistens. Tailwind tvinger deg til å bruke forhåndsdefinerte verdier — p-4 (1rem), p-6 (1.5rem), p-8 (2rem). Ingen vilkårlige pikselverdier som padding: 13px eller margin-top: 7px. Resultatet er at hele appen føles visuelt sammenhengende, selv når forskjellige utviklere jobber på forskjellige deler.

Glassmorphism-designsystemet på porteføljen

Denne porteføljen bruker en glassmorphism-estetikk — halvtransparente elementer med blur-effekter over en mørk bakgrunn. Med Tailwind kan jeg definere dette som et konsistent mønster uten en eneste custom CSS-klasse:

function GlassCard({ children, className }: { children: React.ReactNode; className?: string }) {
  return (
    <div className={`
      rounded-2xl
      bg-white/5
      backdrop-blur-xl
      border border-white/10
      shadow-lg shadow-black/20
      transition-all duration-300
      hover:bg-white/10 hover:border-white/20 hover:shadow-xl
      ${className ?? ''}
    `}>
      {children}
    </div>
  );
}

// Brukes slik:
<GlassCard className="p-6">
  <h3 className="text-lg font-semibold text-white">Prosjektnavn</h3>
  <p className="mt-2 text-sm text-gray-400">Beskrivelse her.</p>
</GlassCard>

Legg merke til mønsteret: basisstilen er i komponenten, men spacing og innhold er fleksibelt via className-propen. Hover-effekten (hover:bg-white/10) er deklarert rett i markup. Ingen separate :hover-regler i en CSS-fil.

Responsive design uten media queries

En av Tailwinds største styrker er responsive modifikatorer. Istedenfor å skrive media queries i en separat fil, definerer jeg responsive atferd direkte:

<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
  {projects.map((project) => (
    <GlassCard key={project.slug} className="p-6">
      <h3 className="text-base font-semibold text-white md:text-lg">
        {project.title}
      </h3>
      <p className="mt-2 text-sm leading-relaxed text-gray-400">
        {project.excerpt}
      </p>
    </GlassCard>
  ))}
</div>

grid-cols-1 md:grid-cols-2 lg:grid-cols-3 — én kolonne på mobil, to på tablet, tre på desktop. Alt på én linje. Ingen @media (min-width: 768px) spredt utover forskjellige filer.

Prefixene er mobile-first: uprefixede klasser gjelder alltid, md: gjelder fra 768px, lg: fra 1024px. Det tvinger deg til å designe mobil først, som er god praksis uansett.

Tilpasning via konfigurasjonen

Tailwind ut av boksen er bra, men den virkelige kraften kommer når du tilpasser konfigurasjonen til prosjektets designsystem:

// tailwind.config.ts
const config = {
  theme: {
    extend: {
      colors: {
        glass: {
          light: 'rgba(255, 255, 255, 0.05)',
          medium: 'rgba(255, 255, 255, 0.10)',
          heavy: 'rgba(255, 255, 255, 0.20)',
        },
      },
      backdropBlur: {
        xs: '2px',
      },
      animation: {
        'fade-in': 'fadeIn 0.5s ease-out',
        'slide-up': 'slideUp 0.6s ease-out',
      },
    },
  },
};

Nå kan jeg bruke bg-glass-light, bg-glass-medium og bg-glass-heavy overalt i prosjektet. Hvis designet endrer seg, oppdaterer jeg verdien ett sted og alt følger med. Det er et ekte designsystem — ikke bare tilfeldige utility-klasser.

Når Tailwind IKKE er svaret

Tailwind er ikke perfekt for alt. For kompleks animasjonslogikk, der keyframes avhenger av JavaScript-state, er det ofte bedre å bruke CSS-in-JS eller vanlig CSS med CSS-variabler. For tredjepartskomponenter som kommer med egen styling, kan det bli rotete å overstyre med Tailwind-klasser.

Og for enkle statiske sider der du skriver HTML for hånd uten komponenter? Da mister du den største fordelen — gjenbrukbare komponentmønstre — og ender opp med duplisert markup.

Oppsummering

Tailwind CSS handler ikke om å skrive CSS på en annen måte. Det handler om å bygge et designsystem direkte i komponentkoden. Ingen navngivning, ingen filer å holde synkronisert, ingen vilkårlige verdier. Kombinert med React-komponenter gir det en utvikleropplevelse der design og kode lever i perfekt harmoni.

Start med de innebygde verdiene, bygg komponentmønstre som GlassCard, og utvid konfigurasjonen når prosjektet krever det.

#tailwind#css#frontend#design

Nyhetsbrev

Få nye innlegg rett i innboksen.