It’s not too late to learn the box-model!

Nulab currently has three front-end engineers, including me. Usually, we write the CSS, but sometimes our engineers also wind up writing some when adding or correcting details.

The problem is that engineers tend to be not-so-good at CSS. Usually they are self-taught and confused about how to use it. So, we held an in-office seminar to teach CSS basics to our engineers. I’d like to share one of the most popular topics from that seminar: the CSS box-model.

Box-model is one of the most basic CSS concepts. If you don’t understand it, you will not be able to realize the layout you envision and want to express.

The Generated Box

Every element of HTML generates a square area called a box. There are two main types of boxes: block and inline. Some of you must have heard these terms before, right? They are the values for the CSS display property.

The default value for the display property (and thus the box-type) of any HTML element is set by the browser’s default style sheet. These can be changed by setting the display property to a different value in your style sheet.

On Google Chrome, “block” is the default value of the display property for the h1 elementOn Google Chrome, “block” is the default value of the display property for the h1 element

Now let’s look at the characteristics of these boxes.

Block Boxes

When its “display” value is “block” (or “table”), an element will generate a block-type box. Elements like h1 through h6, p, div, ul, ol, li, and table generate block boxes by default.

Regardless of their width, block boxes will be laid out vertically, from top to bottom. It may be easier to understand if you imagine that there is a line break before and after a block box, as with a paragraph, so each block has its own vertical space.

Other important characteristics of a block box:

  • It can have a specific width and height. If a specific width is not set, it will spread to fill the whole width of parent element.
  • It can have margins and padding, on any side – up, down, left, and right.

Diagram of two block boxesDiagram of two block boxes

Inline Boxes

When its “display” value is “inline” (or “inline-table”), an element will generate an inline-type box. Elements like span, a, em, strong, and img generate inline boxes by default.

Inline boxes are laid out horizontally, from left to right. There is no “line break” before and after them, they are laid out one after another on the same line.

Other important characteristics of an inline box:

  • It cannot have a specific width or height. *1
  • It cannot have specific margins on the top or bottom.

Diagram of inline boxesDiagram of inline boxes

*1 There are some inline elements that can have specific width and height, for example: img, input, and textarea. These elements are called replaced elements. They have HTML attributes (width, height, size, col etc) that can be used to specify width and height via CSS.

Supplementary: The Inline-block box

A third type of box is the “inline-block.” It is laid out horizontally like an inline box, but can accept specific width, height, margins, and padding like a block box. These boxes are very useful for laying out horizontal navigations, and similar interfaces.

Display Property

The main values for the display property, and the type of box they generate are as follows:

Display Property Box Type
block block
inline inline
inline-block inline-block
list-item A block box for the content and an inline box for the item marker
table, table-row, table-cell, etc. A box equivalent to the box for the corresponding HTML element
none no box is generated

Caution

Since HTML5, CSS should define how things look, and HTML should define the document structure (“semantics”). So, for example, if you want to make a list with bullet points, it is best to use the HTML element that suits this semantic (ul and li), rather than using a non-semantic div with the display property set to “list-item.”

The Box-Model

To lay things out with CSS, you need to understand the box-model, which has four properties, as shown in the diagram, below.

Box-model explanation diagramBox-model explanation diagram

Content Dimensions (Height & Width)

The content itself is the text, images and other things inside an element. Using the height and width properties, you can specify the dimensions of the area that displays the content.

Padding

This is the space between the content and its border. With the padding property you can increase or decrease the size of that space.

Border

This is the box’s demarcation line, outside the padding but inside the margin. It is like a “frame.” You can specify the thickness of this frame using the border-width property.

Margin

This is the outermost property of the box: the space between it’s border and other boxes. You can specify the size of this space using the margin property.

Box-Model Calculations

Look at the example below. Why does the child element (.box__inner) stick out from its parent element (.box) even though its width is set to 100%? (Please check the HTML and CSS by switching the tabs.)

See the Pen XdmbBb by johnykei (@johnykei) on CodePen.

This is very easy for those who know CSS well, but beginners often make mistakes here.

The box size is calculated as the sum total of ‘content + padding + border + margin’. As explained earlier, the width and height properties specify the size of the content area; in the above example the width of “.box” is set to 500px. For“.box__inner,” the width is set to “100%” of its parent’s width (500px). Its padding is set to 10px, and its border is set to 3px. So, the total width of “.box__inner” becomes 500 + 20 (10px padding on each side) + 6 (3px border on each side), 526px.

This is why it is bigger than its parent, despite us having set its width to be 100% of its parent! How can we prevent this? There are 2 approaches:

Method 1: Calculate

With the above understanding, we can calculate the correct width and specify it exactly. If we subtract the padding, border and margin we can specify the correct content area width. In the above example, it would be 500 (the width of the parent content area) – 20 (the total padding width) – 6 (the total border width): so the width of “box__inner” should be “474px” instead of “100%.”

.box__inner {
    width: 474px; /* 500px - 20px - 6px */
    padding: 10px;
    background-color: #fff4c3;
    border: 3px solid #ff8410;
}

You could do it this way, we used to, but it is troublesome. To avoid this trouble, you could use CSS processors like SASS, or calc(), a CSS function that does the calculations for us.

.box__inner {
    width: calc(100% - 20px - 6px);
    padding: 10px;
    background-color: #fff4c3;
    border: 3px solid #ff8410;
}

The calc() function can be used in all major modern browsers now, without the need for a vendor prefix, in most cases. See:
http://caniuse.com/#feat=calc

Method 2: Use Box-Sizing

You can use the “box-sizing” property to specify which area will be affected by the dimensions set in the width and height properties.

Box-sizing explanatory diagramBox-sizing explanatory diagram

Valid values for box-sizing are:

  • content-box: Width and height specify the dimensions of the content area. This is the default setting.
  • padding-box: Width and height include the padding area with the content area.
  • border-box: Width and height include the border and the padding area with the content area.

Thus, in the above example you can prevent the child element from sticking out of the parent element just by using “box-sizing: border-box.” There is no need to calculate width.

.box__inner {
    width: 100%;
    padding: 10px;
    background-color: #fff4c3;
    border: 3px solid #ff8410;
    box-sizing: border-box;
}

With “box-sizing: border-box”, CSS layout becomes much easier. If you use a pre-written CSS library like sanitize.css, “box-sizing: border-box” will be applied to the root element, cascading to every child element so there’s no need to apply it individually.

Lately, CSS frameworks like Bootstrap and others are making it a norm to apply “box-sizing: border-box” to all elements. It works across most browsers (see: http://caniuse.com/#feat=css3-boxsizing), so I recommend it over taking the trouble to calculate the width each time

Margin Cancellations

As I explained earlier, “block” boxes can have vertical margins. If these margins are adjacent to one another, however, they do not accumulate as you might expect. When your margins are not expanding the way you expect, most of the time this is the problem.

Margin cancellation may seem complicated and hard to use, but there are cases where you can use it effectively to streamline your CSS, so let’s understand it correctly.

When Does it Happen?

Margin cancellation affects the top or bottom margin of boxes that are next to each other, vertically – but it only happens in certain cases:

Vertically Adjacent Boxes

When boxes are vertically adjacent (and on the same level), only the bigger margin will be applied. Look at the example below. Box 1 has a 15px “margin-bottom,” and box 2 below it has a 30px “margin-top.” You may think the margin should become the sum of these two, 45px, but in fact the smaller margin of Box 1 is cancelled, and only the bigger margin of .box2 is applied – resulting in a margin of 30px.

See the Pen LNpVJW by johnykei (@johnykei) on CodePen.

Nested Boxes

If elements are nested within one another (without intervening content or space) the largest of all the specified margins will be applied. It is difficult to understand only from words, so please look at the example below.

See the Pen WwQvaP by johnykei (@johnykei) on CodePen.

The parent element has a “margin-top” of 30px, but the actual margin applied is 60px, because the child element has a “margin-top” of 60px. The smaller “margin-top” of the parent has been cancelled by the larger “margin-top” of the child. However, if the parent element had a border or padding, or if it contained text or other content, this cancellation would not occur. Please see the example below. It is safe to remember that margin cancellation will happen as a result of nesting only when the parent and child element are immediately adjacent.

See the Pen RaWPqx by johnykei (@johnykei) on CodePen.

There are other cases where margin cancellation will not happen. I listed some below.

In general, margins will not be cancelled…

  • For horizontal (left and right) margins
  • For “Inline-block” boxes
  • For boxes that are set to“float”

Nested boxes will not cancel their margins…

  • When the parent has padding or border
  • When the parent’s “position” is “absolute,” or “fixed”
  • When the parent’s “overflow” is set as “hidden” or “scroll”

For now, I will skip the detailed explanation of each.

Advantages of Margin Cancellation

Some people may think, ‘Why does this cancellation happen?’ It’s just an obstacle. It’s difficult and has no merit.’ Sure, it is a little difficult when margins cancel unexpectedly, until you get used to it. There are counter-measures to avoid unexpected cancellations. For example, you could decide to only use top, or only bottom margins. (Dropbox specifies this in their style guide. They only use margin-bottom, to avoid unintentional margin cancellations) Or, you could use padding instead of margin, since padding does not cancel.

However, as I said earlier, there are cases where the code will be more complicated if you do not make use margin cancellation. Blog posts, for example, have different HTML in every post. If you wanted to make proper margins for every element in every article, it would be difficult to do that with single-direction margin or padding. Margin cancellation would be very effective here. It avoids irregularities, and is very effective when you incorporate design into web applications, so I especially hope that engineers will learn to use margin cancellation to their advantage.

When to use Margin or Padding

We’ve seen that margin and padding, though they can be a bit troublesome, are important to use correctly. They have different uses, which I will summarize now. This may be totally obvious to some, but I hope you will be able to use it as a good reference.

Use margins…

  • When you want space outside the element’s border / frame
  • When you want transparent space, without the element’s background color or image
  • When you want to use “auto” to define that space (which is very useful for things like centering content)
  • When you want adjacent spaces to cancel instead of accumulate.
  • When you want negative space (margins that have negative value)

Use padding…

  • When you want space inside the element’s border / frame
  • When you want the space to include the element’s background color or image
  • When you want adjacent spaces to accumulate, not cancel

Summary

Did you like the article?

What I wrote here is very basic, but for many people it is surprisingly difficult to remember clearly. I hope it will help you advance to a clearer understanding of CSS.


We are hiring in New York, Tokyo, Kyoto and Fukuoka now! For more details

Try Backlog for 30 days.

Join 800,000 developers running on Backlog. No credit card required.

Try It Free