Tilbake
4.5
Avansert CSS – Flexbox og Grid

4.5 Avansert CSS – Flexbox og Grid

Mestre CSS Flexbox og Grid for avanserte og fleksible sideoppsett.

75 min
8 oppgaver
FlexboxCSS Gridfr-enhetgrid-template
Du leser den tradisjonelle versjonen
Din fremgang i kapitlet
0 / 8 oppgaver

Avansert CSS – Flexbox og Grid

I kapittel 4.3 ble flexbox og grid kort introdusert. Nå skal vi gå i dybden på disse to kraftige layout-modulene i CSS. Flexbox og grid har revolusjonert måten vi lager sideoppsett på – før disse verktøyene fantes måtte utviklere bruke kreative triks med float, tabeller og absolutt posisjonering for å oppnå selv enkle layout.

Flexbox er en endimensjonal layout som jobber langs én akse – enten horisontalt eller vertikalt. Den er perfekt for å fordele plass mellom elementer i en rad eller kolonne, sentrere innhold, og lage navigasjonsmenyer og kortlayout.

CSS Grid er en todimensjonal layout som jobber med både rader og kolonner samtidig. Den er ideell for helhetlige sideoppsett, bildegallerier, dashbord og situasjoner der du trenger presis kontroll over plassering i et rutenett.

Å vite når du skal bruke flexbox og når du skal bruke grid er en viktig ferdighet. Tommelregelen er: bruk flexbox for komponenter og endimensjonal fordeling, bruk grid for sideoppsett og todimensjonale strukturer. I praksis brukes begge ofte sammen i samme prosjekt.

Flexbox (Flexible Box Layout)
Flexbox er en CSS-layoutmodul som arrangerer elementer langs én akse. Den aktiveres med display: flex på foreldreelementet, som da blir en flex-container. Alle direkte barn av containeren blir flex-elementer. Flexbox har to akser: hovedaksen (som standard horisontal) og kryssaksen (som standard vertikal). Egenskaper på containeren styrer fordelingen langs disse aksene, mens egenskaper på barna styrer hvordan hvert enkelt element oppfører seg.

Når du setter display: flex på et element, får du tilgang til flere egenskaper som styrer hvordan barna arrangeres:

flex-direction – Bestemmer retningen på hovedaksen:

.container {
  display: flex;
}

/* Standard: Horisontalt fra venstre til høyre */
.container { flex-direction: row; }

/* Horisontalt fra høyre til venstre */
.container { flex-direction: row-reverse; }

/* Vertikalt fra toppen og ned */
.container { flex-direction: column; }

/* Vertikalt fra bunnen og opp */
.container { flex-direction: column-reverse; }

flex-wrap – Bestemmer om elementene brytes til ny linje:

/* Ikke bryt linjer (standard, elementene krympes) */
.container { flex-wrap: nowrap; }

/* Bryt til ny linje når plassen er full */
.container { flex-wrap: wrap; }

gap – Avstand mellom flex-elementer:

.container {
  display: flex;
  gap: 1rem;        /* Lik avstand i alle retninger */
  gap: 1rem 2rem;   /* rad-avstand kolonne-avstand */
}

De to viktigste justeringsegenskapene i flexbox er justify-content (fordeling langs hovedaksen) og align-items (justering langs kryssaksen).

justify-content – Fordeler plass langs hovedaksen:

.container {
  display: flex;
  justify-content: flex-start;    /* Elementer til venstre (standard) */
  justify-content: flex-end;      /* Elementer til høyre */
  justify-content: center;        /* Elementer sentrert */
  justify-content: space-between; /* Lik avstand mellom, ingen i kantene */
  justify-content: space-around;  /* Lik avstand rundt hvert element */
  justify-content: space-evenly;  /* Helt lik avstand overalt */
}

align-items – Justerer elementer langs kryssaksen:

.container {
  display: flex;
  height: 300px;
  align-items: stretch;     /* Strekk til full høyde (standard) */
  align-items: flex-start;  /* Juster til toppen */
  align-items: flex-end;    /* Juster til bunnen */
  align-items: center;      /* Sentrer vertikalt */
  align-items: baseline;    /* Juster etter tekstens grunnlinje */
}

Sentrering med flexbox – Den enkleste måten å sentrere et element både horisontalt og vertikalt:

.sentrert-container {
  display: flex;
  justify-content: center;  /* Horisontal sentrering */
  align-items: center;      /* Vertikal sentrering */
  height: 100vh;
}

Denne teknikken er ekstremt nyttig og brukes overalt i moderne webdesign. Før flexbox var vertikal sentrering en av de mest frustrerende oppgavene i CSS.

✏️Eksempel: Fleksibel navigasjonslinje

Her er et eksempel på en navigasjonslinje med logo til venstre og menyelementer til høyre:

<header class="navbar">
  <div class="logo">SkoleSaga</div>
  <nav class="nav-lenker">
    <a href="/">Hjem</a>
    <a href="/kurs">Kurs</a>
    <a href="/oppgaver">Oppgaver</a>
    <a href="/om">Om oss</a>
  </nav>
</header>

.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem 2rem;
  background-color: #1a1a2e;
  color: white;
}

.logo {
  font-size: 1.5rem;
  font-weight: bold;
  color: #667eea;
}

.nav-lenker {
  display: flex;
  gap: 1.5rem;
}

.nav-lenker a {
  color: white;
  text-decoration: none;
  padding: 0.5rem 0;
  border-bottom: 2px solid transparent;
  transition: border-color 0.3s;
}

.nav-lenker a:hover {
  border-bottom-color: #667eea;
}

justify-content: space-between.navbar plasserer logoen helt til venstre og navigasjonen helt til høyre med all ledig plass imellom. Selve navigasjonen er også en flex-container med gap: 1.5rem mellom lenkene. Hovrer-effekten med border-bottom gir en elegant understreking uten å flytte andre elementer.

Mens flex-container-egenskapene styrer helheten, kan du også kontrollere individuelle flex-elementer:

flex-grow – Hvor mye et element skal vokse relativt til andre:

.element-a { flex-grow: 1; }  /* Får 1 andel av ledig plass */
.element-b { flex-grow: 2; }  /* Får 2 andeler av ledig plass */
.element-c { flex-grow: 0; }  /* Vokser ikke (standard) */

flex-shrink – Hvor mye et element krymper når plassen er trang:

.element { flex-shrink: 1; }  /* Krymper proporsjonalt (standard) */
.element { flex-shrink: 0; }  /* Krymper aldri */

flex-basis – Startstørrelsen til elementet før vekst/krymping:

.element { flex-basis: 200px; }  /* Starter med 200px bredde */
.element { flex-basis: 30%; }    /* Starter med 30% av containeren */
.element { flex-basis: auto; }   /* Bruker innholdets størrelse (standard) */

flex-shorthand – Kombinerer grow, shrink og basis:

.element { flex: 1; }           /* flex-grow: 1, flex-shrink: 1, flex-basis: 0% */
.element { flex: 0 0 250px; }   /* Ikke voks, ikke krymp, 250px bred */
.element { flex: 2 1 auto; }    /* Voks dobbelt, krymp normalt, auto basis */

Et vanlig mønster er sidebar-layout med flexbox:

.side-layout {
  display: flex;
  gap: 2rem;
}

.sidebar {
  flex: 0 0 250px;   /* Fast bredde, krymper ikke */
}

.hovedinnhold {
  flex: 1;           /* Fyller resten av plassen */
}

CSS Grid Layout
CSS Grid er en todimensjonal layout-modul som lar deg definere et rutenett av rader og kolonner der elementer kan plasseres presist. Grid aktiveres med display: grid på foreldreelementet, og strukturen defineres med grid-template-columns og grid-template-rows. Elementer kan plasseres automatisk i rekkefølge eller manuelt med grid-column og grid-row. Grid er det mest kraftfulle layout-verktøyet i CSS og er ideelt for helhetlige sideoppsett.

Du oppretter et grid ved å sette display: grid og definere kolonnene:

/* Tre kolonner med fast bredde */
.rutenett {
  display: grid;
  grid-template-columns: 200px 400px 200px;
  gap: 1rem;
}

/* Tre like brede kolonner med fr-enheter */
.rutenett {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 1rem;
}

/* Kortform med repeat() */
.rutenett {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}

fr-enheten (fraction) representerer en andel av tilgjengelig plass. I 1fr 2fr 1fr får den midterste kolonnen dobbelt så mye plass som de andre:

.layout {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;
  gap: 1.5rem;
}

Rader defineres med grid-template-rows:

.layout {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: auto 1fr auto;  /* header, innhold, footer */
  gap: 1rem;
  min-height: 100vh;
}

Her er den første og siste raden (header og footer) auto-dimensjonert etter innholdet, mens den midterste raden (innholdet) tar all resterende plass med 1fr.

Du kan plassere elementer manuelt i gridet med grid-column og grid-row:

.rutenett {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: auto auto auto;
  gap: 1rem;
}

/* Elementet spenner over kolonne 1 til 3 (to kolonner) */
.bred-element {
  grid-column: 1 / 3;
}

/* Elementet spenner over alle 4 kolonner */
.full-bredde {
  grid-column: 1 / -1;
}

/* Elementet spenner over 2 rader */
.høy-element {
  grid-row: 1 / 3;
}

Du kan også bruke span for å angi antall spor:

.bred-element {
  grid-column: span 2;  /* Spenner over 2 kolonner */
}

.høy-element {
  grid-row: span 3;     /* Spenner over 3 rader */
}

grid-template-areas gir en visuell måte å definere layout på:

.side-layout {
  display: grid;
  grid-template-columns: 250px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header  header"
    "sidebar innhold"
    "footer  footer";
  gap: 1rem;
  min-height: 100vh;
}

.header   { grid-area: header; }
.sidebar  { grid-area: sidebar; }
.innhold  { grid-area: innhold; }
.footer   { grid-area: footer; }

Med grid-template-areas kan du «tegne» layouten som en visuell representasjon i CSS-koden. Hvert ord representerer et område, og elementene kobles til områdene med grid-area.

✏️Eksempel: Komplett sidelayout med Grid

Her er en komplett sidelayout med header, sidebar, hovedinnhold og footer:

<div class="side-layout">
  <header class="topp">
    <h1>Min nettside</h1>
    <nav>
      <a href="/">Hjem</a>
      <a href="/artikler">Artikler</a>
      <a href="/kontakt">Kontakt</a>
    </nav>
  </header>

  <aside class="venstremeny">
    <h3>Kategorier</h3>
    <ul>
      <li><a href="#">HTML</a></li>
      <li><a href="#">CSS</a></li>
      <li><a href="#">JavaScript</a></li>
    </ul>
  </aside>

  <main class="hoveddel">
    <h2>Siste artikler</h2>
    <article>
      <h3>Lær CSS Grid</h3>
      <p>CSS Grid gjør det enkelt å lage avanserte sideoppsett...</p>
    </article>
  </main>

  <footer class="bunn">
    <p>© 2025 Min nettside</p>
  </footer>
</div>

.side-layout {
  display: grid;
  grid-template-columns: 220px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "topp    topp"
    "meny    hoveddel"
    "bunn    bunn";
  gap: 0;
  min-height: 100vh;
}

.topp {
  grid-area: topp;
  display: flex;
  justify-content: space-between;
  align-items: center;
  background-color: #2c3e50;
  color: white;
  padding: 1rem 2rem;
}

.topp nav {
  display: flex;
  gap: 1rem;
}

.topp nav a {
  color: white;
  text-decoration: none;
}

.venstremeny {
  grid-area: meny;
  background-color: #ecf0f1;
  padding: 1.5rem;
}

.venstremeny ul {
  list-style: none;
  padding: 0;
}

.venstremeny li {
  margin-bottom: 0.5rem;
}

.venstremeny a {
  color: #2c3e50;
  text-decoration: none;
}

.hoveddel {
  grid-area: hoveddel;
  padding: 2rem;
}

.bunn {
  grid-area: bunn;
  background-color: #2c3e50;
  color: white;
  text-align: center;
  padding: 1rem;
}

Denne layouten bruker grid-template-areas for en oversiktlig struktur. Headeren og footeren spenner over hele bredden, mens sidemenyen og hovedinnholdet deler midtseksjonen. Selve headeren bruker flexbox internt for å plassere logoen og navigasjonen – et godt eksempel på at grid og flexbox ofte brukes sammen.

En av de mest nyttige grid-teknikkene er auto-fit og auto-fill med repeat() og minmax(). De lager rutenett som automatisk tilpasser antall kolonner til tilgjengelig plass, helt uten media queries:

/* auto-fit: Tilpasser antall kolonner, strekker eksisterende elementer */
.kort-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.5rem;
}

/* auto-fill: Tilpasser antall kolonner, beholder tomme spor */
.kort-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1.5rem;
}

Forskjellen mellom auto-fit og auto-fill:
- auto-fit: Kollapser tomme spor og lar eksisterende elementer strekke seg. Hvis du har tre elementer i en bred container, kan de bli større enn minimum.
- auto-fill: Beholder tomme spor selv om det ikke er elementer som fyller dem. Elementene beholder sin minimale bredde.

I de fleste tilfeller er auto-fit det du vil bruke, fordi det gir et ryddigere resultat uten usynlige tomme kolonner.

minmax(280px, 1fr) betyr at hver kolonne er minst 280px bred, men kan vokse for å dele tilgjengelig plass. Nettleseren beregner automatisk hvor mange kolonner som får plass:
- Viewport 600px: 2 kolonner (ca. 280px hver)
- Viewport 900px: 3 kolonner (ca. 280px hver)
- Viewport 1200px: 4 kolonner (ca. 280px hver)

Dette er en ekstremt kraftig teknikk som gir responsivt design uten en eneste media query.

Både flexbox og grid er layout-verktøy, men de har ulike styrker:

EgenskapFlexboxGrid
DimensjonerÉn (rad ELLER kolonne)To (rader OG kolonner)
InnholdsbasertJa, elementer bestemmer størrelseNei, rutenettet bestemmer størrelse
Beste forKomponenter, menyer, fordelingSideoppsett, rutenett, dashbord
JusteringSvært fleksibelt langs én aksePresis kontroll i begge akser

Bruk flexbox når:
- Du trenger å fordele elementer i en rad eller kolonne
- Elementene har ulik størrelse og skal fordele plass seg imellom
- Du lager navigasjonsmenyer, verktøylinjer eller kortrekker
- Du vil sentrere et element horisontalt og/eller vertikalt

Bruk grid når:
- Du trenger layout med både rader og kolonner
- Du vil plassere elementer presist i et rutenett
- Du lager helhetlige sideoppsett med header, sidebar og footer
- Du lager bildegallerier eller dashbord med ulike kortsstørrelser

Bruk begge sammen:
I praksis bruker du ofte grid for den overordnede sidelayouten og flexbox for komponenter inni grid-cellene. For eksempel kan headeren være en grid-area, mens innholdet inni headeren arrangeres med flexbox.

✏️Eksempel: Dashboard med Grid og Flexbox

Her er et dashbord som kombinerer grid for overordnet layout og flexbox for innholdet i kortene:

<div class="dashboard">
  <div class="statistikk-kort bred">
    <h3>Besøkende i dag</h3>
    <span class="tall">1 247</span>
    <span class="endring positiv">+12%</span>
  </div>
  <div class="statistikk-kort">
    <h3>Sidevisninger</h3>
    <span class="tall">3 891</span>
    <span class="endring positiv">+8%</span>
  </div>
  <div class="statistikk-kort">
    <h3>Avvisningsrate</h3>
    <span class="tall">34%</span>
    <span class="endring negativ">-2%</span>
  </div>
  <div class="statistikk-kort">
    <h3>Nye brukere</h3>
    <span class="tall">189</span>
    <span class="endring positiv">+23%</span>
  </div>
  <div class="statistikk-kort">
    <h3>Gjennomsnittlig tid</h3>
    <span class="tall">4:32</span>
    <span class="endring negativ">-5%</span>
  </div>
</div>

/* Overordnet layout med Grid */
.dashboard {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1.5rem;
  padding: 2rem;
  background-color: #f0f2f5;
}

/* Element som spenner over to kolonner */
.statistikk-kort.bred {
  grid-column: span 2;
}

/* Hvert kort bruker Flexbox internt */
.statistikk-kort {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  background-color: white;
  padding: 1.5rem;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  min-height: 120px;
}

.statistikk-kort h3 {
  font-size: 0.85rem;
  color: #666;
  margin: 0;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.tall {
  font-size: 2rem;
  font-weight: bold;
  color: #1a1a2e;
}

.endring {
  font-size: 0.9rem;
  font-weight: 600;
}

.endring.positiv {
  color: #27ae60;
}

.endring.negativ {
  color: #e74c3c;
}

Dashboardet bruker grid med auto-fit for å automatisk tilpasse kortene til skjermbredden. Det brede kortet spenner over to kolonner med grid-column: span 2. Inne i hvert kort brukes flexbox med flex-direction: column og justify-content: space-between for å fordele overskrift, tall og endringsprosent jevnt vertikalt.

Flexbox og Grid er de to viktigste layout-verktøyene i moderne CSS:

- Flexbox er endimensjonal og perfekt for å fordele elementer i en rad eller kolonne. De viktigste egenskapene er flex-direction, justify-content, align-items, gap og flex-shorthand.
- CSS Grid er todimensjonal og ideelt for sideoppsett med rader og kolonner. De viktigste egenskapene er grid-template-columns, grid-template-rows, grid-template-areas, gap og fr-enheten.
- auto-fit med minmax() gir responsivt rutenett uten media queries.
- grid-template-areas gir en visuell måte å definere layout i CSS.
- Bruk begge sammen: Grid for overordnet sidelayout, flexbox for komponenter.
- gap er enklere enn margin for avstand mellom elementer i både flexbox og grid.

Med god forståelse av flexbox og grid kan du lage nesten hvilken som helst layout uten å ty til gamle teknikker som float og absolutt posisjonering.

📝Oppgave 4.5.1

Hva er den viktigste forskjellen mellom CSS Flexbox og CSS Grid?

📝Oppgave 4.5.2

Hva gjør følgende CSS?

.container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

📝Oppgave 4.5.3

Hva betyr grid-template-columns: 1fr 2fr 1fr?

📝Oppgave 4.5.4

Skriv HTML og CSS for et bildegalleri med CSS Grid. Kravene:
- Bruk auto-fit slik at antall kolonner tilpasser seg automatisk
- Minimum bredde per bilde: 200px
- Avstand mellom bildene: 1rem
- Bildene skal fylle cellene uten å bli forvrengd (bruk object-fit)
- Hvert bilde skal ha avrundede hjørner

📝Oppgave 4.5.5

Lag HTML og CSS for en footer med tre seksjoner side om side:
- Seksjon 1: «Om oss» med en kort tekst
- Seksjon 2: «Lenker» med en liste med fire navigasjonslenker
- Seksjon 3: «Kontakt» med e-post og telefonnummer

Bruk flexbox for å plassere seksjonene side om side med lik bredde. Footeren skal ha mørk bakgrunn og hvit tekst.

📝Oppgave 4.5.6

Lag HTML og CSS for en komplett sidelayout med CSS Grid og grid-template-areas. Layouten skal ha:
- Header som spenner over hele bredden
- En sidebar (250px bred) til venstre
- Hovedinnhold til høyre som fyller resten av plassen
- Footer som spenner over hele bredden
- Siden skal fylle minst hele viewport-høyden
- Bruk grid-template-areas for å definere oppsettet

📝Oppgave 4.5.7

Hva er forskjellen mellom auto-fit og auto-fill i CSS Grid?

/* Alternativ A */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));

/* Alternativ B */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));

📝Oppgave 4.5.8

Du har en flex-container med tre elementer. Hva skjer med elementenes bredde?

.container {
  display: flex;
}

.a { flex: 1; }
.b { flex: 2; }
.c { flex: 1; }

Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.