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
<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 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:
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 most cases, applying
width: 100% to a block level element is either unnecessary or will bring undesirable results.
One case where you might use this 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.
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.