Apple Developer Connection
Advanced Search
Member Login Log In | Not a Member? Contact ADC

Fonts

This article—the second of two—covers horizontal sizing and shows how to determine the width of elements with CSS. The first article covers vertical sizing. Once you’ve mastered both height and width, you should be well on your way to effectively using CSS.

Width

Here we will consider the width of an element, which is part of what’s called horizontal formatting. You may think that paragraphs are always as wide as they can be — as wide as the browser window or the table cell in which they are contained, and generally, you’d be right. But how does this happen? CSS describes it all in detail, and knowing those details is very important.

CSS makes it look very simple, of course. For example, let’s say you want an image to be 300 pixels wide. You’d probably think to write: IMG {width: 300px;}

Again, you’d be right. However, what if you want a heading to be 20 ems wide? The first reaction is to say: H1 {width: 20em;}

It looks good, but you aren’t really setting the width of the whole element. What you’re doing is setting the width of the content area — that is, the actual box which bounds the content. Padding, borders, and margins will be added to that, and thus can potentially make the box wider than 20ems.

In fact, the horizontal space of a regular, non-positioned element is always as wide as its parent’s width, no matter what it looks like. Here’s the formula to determine how much horizontal space an element will actually occupy:

margin-left + border-width-left + padding-left + width +
padding-right + border-width-right + margin-right

So let’s say you have a paragraph which has to be exactly 250 pixels wide, in order, for instance, to align it with an image. You’re putting in a light blue background color, so you want to add some padding to keep the text from touching the edges of the background. You decide that 15 pixels of padding would be fine. Again, you want the background to line up with the image and be exactly 250 pixels wide, so you write:

P.sidebar {padding-left: 15px; padding-right: 15px;
  margin-left: 0; margin-right: 0;
  border-width-left: 0; border-width-right: 0;
  width: 220px; background: #99FFFF;
}

horizontal sizing screenshot

That’s right, the value of width is actually 220 pixels, because you have 15 pixels of padding to the right and left. Thus 220 + 15 + 15 = 250 gets you the result you want. If you change the amount of padding, then you’ll have to adjust your width value:

P.sidebar {padding-left: 10px; padding-right: 10px;
  margin-left: 0; margin-right: 0;
  border-width-left: 0; border-width-right: 0;
  width: 230px;
}

You might think that the whole sum total of the element’s width is now 250 pixels. Actually, that’s not the case. Remember that the sum of the seven properties must always add up to the same value as the width of the parent element. In order to accomplish this, some values are overridden, although which ones depends on the context.

Given the previous example, let’s assume the sidebar paragraph is found in a table cell which is 300 pixels wide, and which is left-justified (text-align: left;). The seven properties must add up to 300px, no matter what the author writes. Because the padding and width have been explicitly set, and the table cell is left-justified, the browser automatically overrides the right margin to make up the difference. Thus, the result is as if you had written:

P.sidebar {padding-left: 10px; padding-right: 10px;
  margin-left: 0; margin-right: 50px;
  border-width-left: 0; border-width-right: 0;
  width: 230px;
}

If the table cell had been right-justified, then the browser would have set the left margin to be 50px; and had the cell been center-aligned, then the left and right margins would be set to equal values (in this case, 25px each).

On the other hand, let’s say that we want to have an element in the 300-pixel table cell which is 280 pixels wide, and centered. There are a number of ways to go about this, but the easiest one is:

P.callout {padding-left: 10px; padding-right: 10px;
  margin-left: 10px; margin-right: 10px;
  border-width: 0;
  width: auto; background: #FFCC99;
}

horizontal sizing screenshot

By setting the width to auto, we’re saying make this value whatever it needs to be. This is actually the default value for width, so we could have just left out the width statement entirely.

Assuming a non-positioned text element like a paragraph or a DIV, browsers will choose to override either the width, or one of the margins. The method of making these choices is outlined in the following table.

Condition Overridden Property
none of the properties margin-left, margin-right, and width is set to auto margin-right in left-to-right languages;
margin-left in right-to-left languages
exactly one of the properties margin-left, margin-right, or width is set to auto the property set to auto
width is set to auto, and one or both of margin-left and margin-right is also set to auto any margins set to auto are set to zero
width is not set to auto, and both of margin-left and margin-right are set to auto the margins are set to equal amounts (thus visually centering the element)

Padding and borders cannot be set to auto, and so cannot be overridden by the browser.

Extra-Wide Elements

Since the seven properties must add up to the width of the parent element, what happens if they add up to more than that amount? Returning to our 300-pixel table cell, let’s assume we have the following paragraph within it:

P.wide {padding-left: 10px; padding-right: 10px;
  margin-left: 10px; margin-right: 10px;
  border-width: 0;
  width: 290px; background: #FF99CC;
}

horizontal sizing screenshot

So now we have an element which is (10 + 10 + 10 + 10 + 290) 330px wide. Since both margins and the width have all been explicitly set, the browser overrides the value of margin-right and sets it to -20px. The seven properties now add up to 300 pixels, and all is well. However, this does mean that visually, the wide element will be wider than its parent. While intuitively this does not make sense, it is permitted under CSS.

The one place where Macintosh browsers usually err is when the element is contained within a table. In this case, the table cell is usually made larger to accommodate the margins, instead of reducing the right (or left) margin as shown in this section. However, when not within tables, then behavior is usually as expected. So if you have a paragraph that is too wide to fit inside a DIV, for example, then the automatic negative-margin behavior should kick in. Another way to get this negative-margin behavior is to explicitly set a negative margin yourself, which tends to work even inside tables.

Inline Elements

The property width is not permitted on inline text elements. If left or right margins are set, then they are applied to the very beginning or end (respectively) of the element, even if it breaks across multiple lines. Thus, a left margin will cause a visual offset just before the beginning of the element, appearing to push it to the left. Similarly, a right margin will create blank space after the end of the element, appearing to push any following text to the left.

Images

Since images have an intrinsic width, the value auto is always replaced with the intrinsic width of the image, and the width can never be overridden by the browser. The author can change the displayed width of an image by assigning an explicit value, thus scaling the image.

More Information