n00b pro

03. CSS box model

Dit hoofdstuk is onderdeel van de cursus CSS. Andere cursussen in dezelfde reeks: HTML, Javascript, C#, Ontwikkelomgeving.

Border, padding & margin

Definities

Definities (van buiten naar binnen):

box model

Gebruik je browser inspector om de waarden te inspecteren (oranje = margin, groen = padding, blauw = content):

box model

Een voorbeeld:

<div>
   <p>In friendship diminution...</p>
   <p>Fact are size cold... </p>
   <p>Unpacked now declared... </p>
</div>
div {
   background-color: #eee;
   border: 5px dotted #900;
   padding: 20px 40px;
}
p {
   background-color: #ccc;
   border: 1px solid black;
   margin: 0 0 10px 0;
   padding: 10px;
}
/* laatste paragraaf geen margin onder  */
p:last-child {
   margin-bottom: 0;
}
            

In friendship diminution instrument so. Son sure paid door with say them.

Fact are size cold why had part. If believing or sweetness otherwise in we forfeited.

Unpacked now declared put you confined daughter improved.

Margins en paddings aangeduid met kleur (groen = padding, oranje = margin, blauw = content):

In friendship diminution instrument so. Son sure paid door with say them.

Fact are size cold why had part. If believing or sweetness otherwise in we forfeited.

Unpacked now declared put you confined daughter improved.

Box-sizing

CSS heeft een vreemde interpretatie van de width en height properties: ze stellen de afmetingen in, maar exclusief borders of paddings. enkel betrekking op de content, zonder borders and paddings. Die worden er achteraf nog bijgeteld. Neem volgend voorbeeld met twee boxen, allebei ingesteld op dezelfde breedte van 300px, de eerste zonder padding en border, de tweede met:

<div class="box" id="box1">
   <h2>box 1</h2>
   <ul>
      <li>height: 300px</li>
      <li>width: 300px</li>
      <li>geen border</li>
      <li>geen padding</li>
   </ul>
   <p>Totaal: 300px + 0 + 0 = <mark>300px</mark> </p>
   <p>Een mislukking men bijzondere primitieve. Doodende tusschen er voorziet vroegere allerlei bezetten te. Reeds sinds jaren onder wilde te na. </p>
</div>
<div class="box" id="box2">
   <h2>box 1</h2>
   <ul>
      <li>height: 300px</li>
      <li>width: 300px</li>
      <li>border: 10px links/rechts</li>
      <li>padding: 50px links/rechts</li>
   </ul>
   <p>Totaal: 300px + 2 * 50px + 2 * 10px = <mark>420px</mark> </p>
   <p>Een mislukking men bijzondere primitieve. Doodende tusschen er voorziet vroegere allerlei bezetten te. Reeds sinds jaren onder wilde te na. </p>
</div>
.box {
   background-color: #eee;
   height: 300px;
   width: 300px;
}
#box2 {
   border-left: 10px solid #666;
   border-right: 10px solid #666;
   padding: 0 50px;
}

Dit is totaal onlogisch! Gelukkig kan dit eenvoudig opgelost worden met de box-sizing property:

* {
   box-sizing: border-box; /* standaardwaarde is content-box */
}

Het voorbeeldfragment wordt dan:

<div class="box" id="box1">
   <h2>box 1</h2>
   <ul>
      <li>height: 300px</li>
      <li>width: 300px</li>
      <li>geen border</li>
      <li>geen padding</li>
   </ul>
   <p>Totaal: 300px + 0 + 0 = <mark>300px</mark> </p>
   <p>Een mislukking men bijzondere primitieve. Doodende tusschen er voorziet vroegere allerlei bezetten te. Reeds sinds jaren onder wilde te na. </p>
</div>
<div class="box" id="box2">
   <h2>box 1</h2>
   <ul>
      <li>height: 300px</li>
      <li>width: 300px</li>
      <li>border: 10px links/rechts</li>
      <li>padding: 50px links/rechts</li>
   </ul>
   <p>Totaal: 300px + 2 * 50px + 2 * 10px = <mark>420px</mark> </p>
   <p>Een mislukking men bijzondere primitieve. Doodende tusschen er voorziet vroegere allerlei bezetten te. Reeds sinds jaren onder wilde te na. </p>
</div>
* {
   box-sizing: border-box; /* breedte is van border tot border */
}
.box {
   background-color: #eee;
   height: 300px;
   width: 300px;
}
#box2 {
   border-left: 10px solid #666;
   border-right: 10px solid #666;
   padding: 0 50px;
}

Zet altijd * { box-sizing: border-box; } aan het begin van je CSS! Zo is een width gewoon een breedte, mét borders en paddings.

Margin of padding?

Er zijn nog andere combinaties van margins en paddings mogelijk. Zolang je geen achtergrondkleuren gebruikt, zul je geen verschil zien. Je kan de paddings links en rechts in het buitenste element bijvoorbeeld vervangen door margins van de paragrafen:

div {
   ...              
   padding: 20px 0;
}
p {
   ...              
   margin: 0 40px;
}
p + p {
   margin-top: 10px;
}
...

In friendship diminution instrument so. Son sure paid door with say them.

Fact are size cold why had part. If believing or sweetness otherwise in we forfeited.

Unpacked now declared put you confined daughter improved.

Je kan ook paddings van het buitenste element combineren met margins van de paragrafen:

div {
   ...              
   padding: 10px 20px;
}
p {
   ...              
   margin: 10px 20px;
}
...

In friendship diminution instrument so. Son sure paid door with say them.

Fact are size cold why had part. If believing or sweetness otherwise in we forfeited.

Unpacked now declared put you confined daughter improved.

Je ziet, de mogelijkheden zijn schier eindeloos. Eigenlijk maakt het niet zoveel uit wat je kiest, maar om een houvast te geven hanteren we in deze cursus volgende vuistregels:

  1. denk van buiten naar binnen: liever margin/padding op de parent, dan margin/padding op de child
  2. denk van linksboven naar rechtsonder: liever margin bottom/right op een element, dan top/left op het volgende (dit geldt ook voor borders: b.v. liever een border onder dan boven een element)
  3. denk standaard aan margins, dus ruimte tussen elementen
  4. denk enkel aan padding bij ruimte binnen elementen, dus tussen rand en de inhoud

Zoals altijd bij vuistregels, zijn er uitzonderingen:

→ volg zoveel mogelijk de vuistregels, maar gebruik je gezond verstand

Margins

Margin bleeding

Eén van de eigenaardigheden van CSS dat zich voordoet bij geneste elementen is margin bleeding: als een parent element geen padding of border heeft, loopt de margin van het child element eruit. Stel dat we dit blokje willen maken, met een titel en een tekst:

We stellen bovenmargin in van de titel, en ondermargin van de tekst, maar dat lijkt niet correct te werken:

<div class="review">
   <h3 class="review-title">Great hotel!</h3>
   <p>
      In friendship diminution instrument so.
      Son sure paid door with say them. Lorem
      ipsum dolor sit amet, consectetur
      adipiscing elit!
   </p>
</div>
.review {
   background-color: #eee;
   max-width: 280px;
   padding: 0 20px;
}
.h3 {
   margin-top: 1em; /* lijkt niet te werken? */
}
.review p {
   font-size: 14px;
   margin-bottom: 1em; /* lijkt niet te werken? */
}

Great hotel!

In friendship diminution instrument so. Son sure paid door with say them. Lorem ipsum dolor sit amet, consectetur adipiscing elit!

de bovenmarge van de titel en ondermarge van de paragraaf lijken verdwenen

De reden is dat marges zonder padding of borders rondom, uit de parent lopen. Met kleuren (oranje = marge, groen = padding, blauw = content):

margins lopen boven en onder uit de parent

Er zijn drie oplossingen voor dit probleem:

oplossing 1: geef de parent een rand
oplossing 2: geef de parent een padding
oplossing 3: stel overflow: hidden in op de parent

Margin collapsing

Nog een eigenaardigheid is margin collapsing: waar verticale margins raken, worden margins onder bepaalde omstandigheden niet opgeteld maar wordt de grootste margin genomen van de twee. Bij horizontale margins bestaat dat niet; daar worden ze altijd opgeteld.

<h2>Great hotel!</h3>
<p>
   In friendship diminution instrument so.
   Son sure paid door with say them. Lorem
   ipsum dolor sit amet, consectetur
   adipiscing elit!
</p>
<button>Verzenden</button>
h2 {
   margin: 20px 20px;
}
p {
   margin: 10px 20px;
}
button {
   margin: 30px 20px;
}
verticale margins tussen <h2> en <p> collapsen wel, die tussen <p> en <button> niet

De voorwaarden voor margin collapsing zijn:

  1. het moet om twee blocklevel elementen gaan
  2. enkel verticale margins kunnen collapsen
  3. de margins moeten raken; er mag geen padding, border of andere content tussen liggen
  4. ze mogen niet gelayout zijn met float, flexbox of absolute positionering (zie volgend hoofdstuk)

De margins van de button en de paragraaf in ons voorbeeld collapsen bijvoorbeeld niet omdat een button een inline-block element is, geen blocklevel element (voorwaarde 1).

Verticale margins van aangrenzende blocklevel elementen, schematisch voorgesteld:

Margins van geneste elementen kunnen ook verticaal collapsen met die van hun parent:

Ook boven- en ondermargins van lege elementen collapsen:

Inline elementen

Voor dit deel vertrekken we van volgende HTML, een tekst met twee aaneengrenzede links:

<p>
   Er de inkomsten af gewijzigd bewegende ze. Zoon diep zal mont zelf rang far een men lage.
   Mogelijk cultures pyrieten interest ik rivieren nu de geschikt. Ook dien tot toe heft komt sago 
   stad zijn kan. Aangaan enclave elk ziedaar als <a href="">zwijnen</a><a href="">stal</a> mee metalen. Elkander wie 
   heerlijk nog oog getracht staatjes kan verbrand. Inboorling vergrooten tinprijzen mislukking 
   zoo wel zij. Een sap cultures schijnen boringen wat mijnbouw bij plaatsen. Far vruchtbaar 
   aan interesten gewasschen uitgegeven per met. Moeten andere den missen het succes dag ten.
</p>

Margins

Bij inline elementen worden verticale margins genegeerd:

a {
   margin: 10px;
}

Merk het verschil op bij inline-block elementen, waar verticale margins wel werken:

a {
   display: inline-block;
   padding: 15px;
}

Paddings

Inline elementen met padding overlappen onderaan, en onderlappen bovenaan:

a {
   padding: 15px;
}

Merk het verschil op bij inline-block elementen:

a {
   display: inline-block;
   padding: 15px;
}

width/height

Je kan geen afmetingen instellen op inline elementen; width en height worden genegeerd. Wil je toch afmetingen instellen, b.v. om van een link een knop te maken, dan moet je eerst de display veranderen naar block of inline-block:

<div>
   <p>Nog geen lid? Registreer vandaag!</p>
   <p><a href="/register">registreer</a></p>
</div>
a {
   background-color: #eee;               
   border: 1px solid #ccc;               
   border-radius: 3px;
   color: #333;
   display: inline-block; /* zonder deze regel worden afmetingen genegeerd */
   font-size: 12px;
   height: 40px; /* hoogte */
   line-height: 40px;
   text-align: center;
   text-decoration: none;
   width: 120px; /* breedte */
}

Nog geen lid? Registreer vandaag!

REGISTREER

Je kan natuurlijk ook paddings gebruiken in plaats van width en height om de button wat groter te maken, maar ook dan kan je beter de display veranderen naar inline-block, of anders krijg je overlappingen zoals hierboven beschreven.

<div>
   <p>Nog geen lid? Registreer vandaag!</p>
   <p><a href="/register">registreer</a></p>
</div>
a {
   background-color: #eee;               
   border: 1px solid #ccc;               
   border-radius: 3px;
   color: #333;
   display: inline-block; /* zonder deze regel werken paddings niet goed */
   padding: 12px 25px;
   font-size: 12px;
   text-align: center;
   text-decoration: none;
}

Nog geen lid? Registreer vandaag!

REGISTREER

Moraal van het verhaal: als je afmetingen of verticale paddings of margins wil, verander de display best naar inline-block of block

De draad kwijt..?

Zoals je ziet, gedragen margins en paddings gedragen zich heel verschillend naargelang het type element. De beste tip die we je kunnen geven: gebruik je inspector tool om de margins, paddings en afmetingen te inspecteren en problemen op te lossen!

box model