# CSS Box Model

## Summary


CSS is used to style HTML documents. An important insight is that, 

> Every element in web design is a rectangular box

No matter how complex the design, at the level of elements, it's just a bunch of boxes. The "box" is an underlying representation. We don't actually see a box unless the designer chooses to show it's border.

Each box has width and height. It's border may or may not be visible. Content resides within the box. Content maybe surrounded by extra spacing. Each box is separated from its neighbouring boxes by defined distances. The CSS Box Model formalizes these ideas in terms of CSS properties and the values they can accept. 

Understanding the box model is essential for any web designer or developer. Browsers have built-in tools that enable developers visualize these boxes during development and debugging.

## Discussion

### Which are the essential elements of the CSS Box Model?

Suppose there's a text element `<div>Hello World!</div>`. Let's assume that content begins at the left edge of the box and flows to the right. Content "Hello World!" is placed within the box. The box has a size defined by **height** and **width**. These dimensions are calculated from the size of the parent element, size of the content or defined explicitly for the element. 

The edge of the box is called the **border**. Border can be invisible, thin (few pixels) or thick (many pixels). It can be a solid line, a dotted line, and so on. It can be in a chosen colour. 

If we include extra spacing within the box along its edges, this is called **padding**. An element usually appears next to other elements (parent or siblings). The separation from one element to the next is defined by **margin**. 

Border, padding and margin can all have different values for each side of the box. Some border properties are inherited by default. Padding and margin are not inherited by default unless declared explicitly. 


### How is margin different from padding?

Margin occurs outside the box to separate elements. Padding occurs within the box to add spacing between box edge and content. To put it differently, margin controls rendering of an element and its neighbours, whereas padding controls rendering of an element and its children. 

Because padding area is within the box, CSS properties applied to the box affect the padding area as well. For example, if the element has green background colour, the padding area will have green background but the margin background colour is not affected. In fact, the margin background colour will be determined by that of the parent element. 

Non-zero padding increases the overall dimensions of the element. Margin adds spacing outside the box. Adding a margin is like shifting the entire box whereas adding padding is like shifting the content within the box. 

Padding can't be negative but margin can be negative. With a negative margin, an element can "jump out" of its parent or overlap with another element.  


### How are width and height of a box determined?

Total width of an element is calculated as `margin-right + border-right + padding-right + width + padding-left + border-left + margin-left`, where `width` is the box width. The calculation for height is similar, using top and bottom rather than right and left. 

If element has CSS declaration `box-sizing: border-box;` then total width changes to `margin-right + width + margin-left`. Padding and border sizes don't affect total box dimensions. Content area shrinks. 

Box width and height can be specified in CSS, for example `width: 50%` and `height: 100px`. Values are either absolute (pixels, points, inches, etc) or relative (percentage of parent, percentage of viewport, fraction of font size, etc). 

If width and height are not specified, they're determined by the content. For block elements, width is 100% of the parent by default. It's better to specify them if the element size is essential to the overall layout. 

If width and height are specified, but if the content requires more space than available, rendering behaviour is controlled by `overflow` property, which can take values `visible`, `hidden`, `scroll` and `auto`. 


### How do I use display CSS property?

CSS `display` property is important since it affects how the box is rendered. Common values for `display` include:  

    + `none`: Element is not displayed. Unlike `visibility:hidden` that hides an element but leaves an empty space, `display:none` leaves no empty space.
    + `inline`: Element is displayed on the same line as adjacent elements. Height and width are determined by the content and can't be set explicitly. This is the default for span, a, img, em, strong, i, small, etc. Only left and right margins are applicable. Padding is applicable on all four sides but top and bottom padding may bleed into lines above and below.
    + `inline-block`: Similar to inline but height and width can be set. Box model properties are applicable here. The problem of vertical bleeding seen in inline is solved with inline-block.
    + `block`: Element is displayed on a separate line and takes up 100% width of the parent. This is the default for div, h1, p, li, section, etc.

### What are some variants of the box model?

While the box model is often displayed as inline, inline-block or block, there are other variants. A specialization of the box model is `display:table`. This obeys block flow. Cells flow into rows and columns. Table box has margins but not padding. Cells have padding but not margins. Properties `border-collapse` and `table-layout` are applicable. 

Another variation is `display:list-item`, equivalent to using `<li>` tag. Property `list-style-type` is applicable. 

It's possible to take out an element from normal flow and put it in a separate layer. This is achieved with property `position`. Common values include `absolute` (relative to closest ancestor), `relative` (relative to itself in normal flow) and `fixed` (relative to viewport, unaffected by scrolling). Such boxes don't affect the position of other boxes. These boxes can overlap freely. Property `z-index` controls how they overlap, with larger values coming on top. 

Another way to take out an element from normal flow is with `float`. Common values include `left`, `right`, `inline-start` and `inline-end`. Unlike `position`, boxes affect adjacent content in the flow. For example, a box floated left will indent adjacent content to the right. 


### What is margin collapsing?

Consider two sibling elements, each set with margin of 20px. With inline-block display, elements are separated by 40px since margins are additive. However, if we change to block display, adjacent margins collapse into a single margin of 20px. Note that padding is not subject to collapsing. 

Collapsed margin size is the largest of the individual margins. If there are negative margins involved, collapsed margin is the most positive or the most negative margin. When all margins are negative, it collapses to the most negative margin. 

Margin collapsing happens for adjacent siblings; when there's no content separating parent and descendants; for empty blocks; and more complex scenarios when these conditions are combined. 

It's been said that margin collapsing is one of design mistakes in CSS. There are rules to when margins can collapse but there are also many exceptions to the rules. This makes it difficult and confusing for a web developer. One way to overcome this complexity is to consistently set right and bottom margins and zero out top and left margins, such as, `margin: 0 40px 40px 0;`. 


### Could you share some tips for working with CSS Box Model?

Here are some useful tips for beginners:

    + If width is not set, it defaults to 100%. Padding and border will push inwards. If width is explicitly set to 100%, padding and border will push outwards as normal.
    + Left and right margins can take the value `auto` to center the element horizontally. This is not possible with padding. For centering vertically, use `display: table-cell; vertical-align: middle;` for the element and `display: table` for its parent. CSS Flexbox offers a simpler approach.
    + To inherit only right margin and fix other margins, use `margin: 10px 0 20px 15px; margin-right: inherit;`.
    + Use `box-shadow` with `rgba` values to improve design quality.
    + To fit images to a certain width without exceeding the original width or distorting it, use `max-width: 100%; height: auto;`.
    + Element height depends on content height and remains unaffected by `height: 100%`. Height can be controlled using padding, such as `height: 0; padding-bottom: 100%;`.
    + Columns with different content can be made to have the same height using large padding and negative margin. Suppose bottom padding is 10px, we can use `margin-bottom: -99999px; padding-bottom: 100009px;`. CSS Flexbox offers a simpler approach.

### Which are some CSS modules that are relevant to the CSS Box Model?

**CSS Intrinsic & Extrinsic Sizing** is the module that talks about `box-sizing` property that's directly relevant to the box model. This property can take values `content-box` (default) and `border-box`. 

The box model relates to only one element. When designing layout, the use of CSS properties `margin`, `display` and `float` are helpful. However, there are CSS3 modules that work with the box model and simplify layout design:

    + **CSS Flexbox**: Children of a container can adjust their sizes to fit the container. This can happen in one dimension, either horizontally or vertically. By nesting, two-dimensional layouts can be achieved.
    + **CSS Grid**: A two-dimensional layout system that's easier to work with than Flexbox. This is a modern alternative to the `<table>` tag from the early days of HTML.
    + **CSS Multi-column**: Content flows into multiple columns with gap and rule between columns.Another useful module is **CSS Box Alignment** that works with layout modules to align elements within their container parent. Elements can be positioned within the parent, spaces between elements can be controlled, and containers can be configured to align the elements within. 

## Milestones

Dec  
1996

W3C publishes *Cascading Style Sheets, level 1*, simply called **CSS1**, to express styling of HTML documents. It borrows from desktop publishing terminology. It states that each formatted element is treated as a rectangular box surrounded by optional padding, border and margin areas. Top and bottom margins can collapse. 

Aug  
2001

Microsoft releases Internet Explorer 6, which conforms to the W3C CSS box model. Earlier releases of IE implemented a modified box model that ignored border and padding when computing the total width or height of an element: `total width = margin-left + width + margin-right`. Effectively, earlier versions of IE reduced content size to make room for border and padding. This behaviour is possible in CSS3 via `box-sizing: border-box;`. 

Aug  
2002

First draft of **CSS2.1** is published, which is a revision of CSS2 from 1997. CSS2.1 becomes a W3C Recommendation in June 2011. For clarify, it adds the terms border edge and padding edge. Inner edge is also called content edge. Outer edge is also called margin edge. Unlike in CSS1, margin, padding and border properties can be **inherited**. 

Oct  
2002

W3C publishes the first working draft of *CSS Box Model Module Level 3*. Subsequent revisions of this draft appear in 2007, 2018 and 2020. The main change is to bring clarity for **vertical writing modes**. 

2011

Bowers et al. publish the book *Pro HTML5 and CSS3 Design Patterns*. They note that to speak of the box model as a single model is an oversimplification. They identify six types of the box model: inline, inline-block, block, table, absolute and floated. 

Apr  
2020

W3C publishes the first public working draft of *CSS Box Model Module Level 4*. Property `margin-trim` is introduced with three possible values: `none`, `in-flow` and `all`. Often we include margins between siblings but we wish to avoid margins before/after first/last sibling since they border the parent container. This property when used on an element trims margins of children that border the container's edges.