What is the CSS box model?
Every element is a rectangle of four layers, inside out: content, padding (takes the background), border, and margin (always transparent).
+------------------- margin -------------------+ | +--------------- border ----------------+ | | | +----------- padding ------------+ | | | | | content | | | | | +--------------------------------+ | | | +---------------------------------------+ | +----------------------------------------------+By default
widthmeasures only the content;box-sizingchanges that. More in the box model docs.What is the difference between box-sizing: content-box and border-box?
With
content-box(the default),widthsets the content only and padding and border are added on top. Withborder-box,widthis the whole box.HTML<style> .box { width: 200px; padding: 20px; border: 5px solid #2563eb; margin-bottom: 8px; background: #dbeafe; } .content { box-sizing: content-box; } .border { box-sizing: border-box; } </style> <div class="box content">content-box</div> <div class="box border">border-box</div> <script> for (const el of document.querySelectorAll('.box')) el.textContent += ': ' + el.offsetWidth + 'px wide'; </script>The first box is 250px (200 + 2 × 20 + 2 × 5), the second 200px, which is why most resets set
border-boxon everything.What is the difference between margin and padding?
Padding is space inside the border and shows the element's background; margin is space outside it and is always transparent. Only margins can be negative or
auto(margin: 0 autocenters a block), and only vertical margins collapse. Space siblings withgapon the parent. See margin vs padding.What is margin collapsing?
Two touching vertical margins become one equal to the larger, not the sum: 30px then 20px leaves 30px.
HTML<style> .a { margin-bottom: 30px; } .b { margin-top: 20px; } .a, .b { background: #2563eb; color: white; padding: 6px; } .flex { display: flex; flex-direction: column; } .note { font: 13px monospace; } </style> <div class="box"><div class="a">block layout</div><div class="b">next</div></div> <div class="box flex"><div class="a">flex column</div><div class="b">next</div></div> <script> for (const box of document.querySelectorAll('.box')) { const [a, b] = box.children; const gap = b.getBoundingClientRect().top - a.getBoundingClientRect().bottom; box.insertAdjacentHTML('afterend', '<p class="note">gap: ' + gap + 'px</p>'); } </script>It happens between siblings, between a parent and its first or last child (the margin leaks out), and on empty blocks. Never horizontally, never in flex or grid (the second box shows 50px), and not across padding, a border or
display: flow-root.What are the values of the overflow property?
visible(the default, content spills out),hidden(clipped),clip(clipped, no scrolling at all),scroll(scrollbars always) andauto(scrollbars when needed).HTML<style> .box { display: inline-block; vertical-align: top; width: 140px; height: 60px; margin: 0 8px 40px 0; border: 2px solid #2563eb; font-size: 13px; } .v { overflow: visible; } .h { overflow: hidden; } .s { overflow: scroll; } .a { overflow: auto; } </style> <div class="box v">visible: this text is too long for the box and spills out below it</div> <div class="box h">hidden: this text is too long for the box and is cut off at the border</div> <div class="box s">scroll: this text is too long for the box, so you scroll it</div> <div class="box a">auto: a scrollbar appears only because this text is too long</div>Trap:
hiddenstill makes a scroll container, which breaksposition: stickyinside it;clipdoes not. Setting onlyoverflow-x: hiddenturnsoverflow-yintoauto, so a vertical scrollbar can appear. More in overflow.Why do width, height and vertical margin not work on a span?
A
spanis inline: its size comes from its text, sowidth,heightand vertical margins are ignored, and vertical padding overlaps the lines around it instead of pushing them away.HTML<style> span { background: #fde68a; } .try { width: 200px; height: 60px; margin: 30px; padding: 10px; } .ib { display: inline-block; } </style> <p>Text before <span class="try">inline span</span> text after, with a second line of text to show that the padding overlaps it.</p> <p>Text before <span class="try ib">inline-block span</span> text after.</p>Use
display: inline-blockorblock. Inside a flex or grid parent aspanis blockified and accepts a width.What is the difference between outline and border?
A border is part of the box and takes space; an outline is drawn outside the border, takes none, never shifts the layout and cannot be set per side. Browsers draw keyboard focus with it, so never write
outline: nonewithout a replacement; style:focus-visible. For debugging,* { outline: 1px solid red; }shows every box.How do you truncate text with an ellipsis?
For one line you need all four: a constrained width,
white-space: nowrap,overflow: hiddenandtext-overflow: ellipsis. For several lines use-webkit-line-clamp, which every current browser supports despite the prefix.HTML<style> p { width: 220px; border: 1px solid #9ca3af; padding: 4px; } .one { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .two { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; } </style> <p class="one">A long product title that will not fit on a single line of this box</p> <p class="two">A longer description that runs over several lines, and the box shows only the first two of them before the dots appear at the end</p>Inside a flex row, the item may refuse to shrink: see the
min-width: 0question.What is the difference between width: auto and width: 100%?
On a block element,
width: autofills the container after subtracting the element's own margin, border and padding.width: 100%makes the content box as wide as the parent's content box, so padding, border and margin are added on top and it overflows.HTML<style> .parent { width: 260px; border: 2px dashed #9ca3af; padding: 4px; } .child { padding: 10px; border: 4px solid #2563eb; margin: 4px 0; background: #dbeafe; } .full { width: 100%; } </style> <div class="parent"> <div class="child">width: auto fits</div> <div class="child full">width: 100% sticks out</div> </div>box-sizing: border-boxfixes the padding and border part, not the margins. On floats and absolutely positioned elements,automeans shrink to fit the content instead.Why is there a small gap under an image inside a div?
Images are inline by default, so they sit on the text baseline, and the line keeps room below the baseline for descenders (the tails of g and p). Fix it with
display: blockon the image, orvertical-align: middle(ortop,bottom) if it must stay inline. An inline<svg>behaves the same, so it stands in for an image here:HTML<style> .box { background: crimson; width: 120px; margin-bottom: 8px; } .fixed svg { display: block; } </style> <div class="box"><svg width="120" height="60"><rect width="120" height="60" fill="#2563eb"/></svg></div> <div class="box fixed"><svg width="120" height="60"><rect width="120" height="60" fill="#2563eb"/></svg></div>The red strip under the first one is that descender space.
CSS Box Model Interview Questions
Content, padding, border and margin, how box-sizing changes the math, and margin surprises.