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.

Use box-sizing: border-box

This was originally an older post that didn’t take into consideration possible use of the border-box property. If you add the following at the top of your CSS file, you should be able to avoid many of the problems inherent in using 100% width on your elements:

* { box-sizing: border-box; }

This ensures padding is factored into the width of your elements. Of course, not all projects use this and this doesn’t fix the fact that margins can affect the position of an inner element. But in most cases, I strongly recommend you use padding inside a box, rather than margins, to ensure you don’t have this problem.

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).

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 width: 100% 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:

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 many cases, applying width: 100% to a block level element is either unnecessary or will bring undesirable results. If you’re using padding on the inner element and you use box-sizing: border-box , then you’ll be safe.

One case where you might use width: 100% is when the element is inheriting a set width value that you want to override. But even in this case, a better option would be to use “width: auto”, which is the default for block elements.

The other instance where this is necessary is when using flexbox, which sometimes requires that an element be set to 100% width in order to take up a full line and override flexbox’s natural manner of spacing elements evenly on a single line. But this depends on what layout you’re trying to achieve.

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 height on the parent, the child element will fill the height to 100% as expected.

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.