Tuesday, June 22, 2010

What Does “width: 100%” Do in CSS?

What Does width: 100% Do in CSS?It seems like this should be one of the easiest things to understand in CSS. If you want a block-level element to fill any remaining space inside of its parent, then it’s simple — just add width: 100% in your CSS declaration for that element, and your problem is solved.

Not so fast. It’s not quite that easy. I’m sure CSS developers of all skill levels have attempted something similar to what I’ve just described, with bizarre results ultimately leading to head scratching and shruggingly resorting to experimenting with absolute widths until we find just the right fit. This is just one of those things in CSS that seems easy to understand (and really, it should be), but it’s sometimes not — because of the way that percentages work in CSS.

First Things First: Blocks Don’t Need 100% Width

When we understand the difference between block-level elements and inline elements, we’ll know that a block element (such as a <div>, <p>, or <ul>, to name a few) will, by default expand to fit the width of its containing, or parent, element (minus any margins it has or padding its parent has).

A Block-Level Element Expands Naturally

Most CSS developers understand this concept pretty well, but I thought it would be useful to point it out here as an introduction to explaining how percentages work when used on the width property.

What it Really Means

When you give an element a width of 100% in CSS, you’re basically saying “Make this element’s content area exactly equal to the explicit width of its parent — but only if its parent has an explicit width.” So, if you have a parent container that’s 400px wide, a child element given a width of 100% will also be 400px wide, and will still be subject to margins, paddings, and borders — on top of the 100% width setting. The image below attempts to illustrate this:

The child's content area will equal the parent's

And of course, the exact same rule would apply to any percentage value. The content area will be the percentage of the parent’s explicitly-set width setting.

NOTE ADDED: The width of the child’s content area will equal the width of the parent’s content area, but will not move outside the parent unless its own padding or margins are affecting it. Thanks to the comment by Fabio Brendolin for clarifying this.

Should it Ever Be Used?

In 99% of cases, applying width: 100% to a block level element is either unnecessary or will bring undesirable results. The only time that I can think of when you need to give an element a width of 100% is when the element is inheriting a set width value that you want to override. But even in this case, the correct option would be to use “width: auto”, which is the default for block elements.

Height Works the Same Way (in All Browsers!)

And this little lesson provides a reminder of one of the frustrating things about CSS layouts — that you can’t give an element a height that fills its parent, unless the parent is given (you guessed it) an explicit height setting. The only difference is that in this case “auto” will not work, but instead “height: 100%” is required.

And the great part is that all browsers (even IE6 and IE7) use percentage height exactly the same (IE bugs excluded), so as long as you explicitly set a width on the parent, the child element will fill the height to 100% as expected.

On a Side Note: “Remainder” should be a value

As a side note to all of this, there are some cases where a group of floated child elements will have varying widths, and it would be great to be able to just tell the last element “fill the remaining space”. On my personal CSS wish list would be a property/value setting as follows:

  1. #element {  
  2.     width: remainder; /* not valid, but I wish it was! */  
  3. }  

This would be nice, and would certainly make things easier in some circumstances.

What do you think? Have you ever misinterpreted percentage widths, and abandoned using them because they didn’t work as you expected? I know I’ve done this, and it took me quite some time to get it right and understand them better.

No comments: