CSS Div width percentage and padding without breaking layout

Kyle Ross picture Kyle Ross · Aug 21, 2010 · Viewed 140.3k times · Source

There may be a simple fix for this, but it has troubled me for ages now...

Let me explain the situation. I have a div with the ID 'container' that holds all the contents in the page (including header and footer also) that will keep everything inline and I can do just 1 simple 'margin:0 auto;' instead of multiples. So lets say that I have the width of #container set to 80%. Now if I put another div inside with the same width (80%) and give it the ID of 'header' with 10px of padding all around, the layout would "break" (so to speak) because the page adds the padding amount onto the width. So, how can I make it stay in-bounds without using methods such as a lower percentage for the #header div? Basically, I want to make it fluid.

Here is some example code to give you an idea of what I am talking about...

CSS

#container {
    position:relative;
    width:80%;
    height:auto;
}
#header {
    position:relative;
    width:80%;
    height:50px;
    padding:10px;
}

HTML

<div id="container">
    <div id="header">Header contents</div>
</div>

Can anyone help me out with this issue that has been bugging me forever?

Answer

Pat picture Pat · Aug 22, 2010

If you want the #header to be the same width as your container, with 10px of padding, you can leave out its width declaration. That will cause it to implicitly take up its entire parent's width (since a div is by default a block level element).

Then, since you haven't defined a width on it, the 10px of padding will be properly applied inside the element, rather than adding to its width:

#container {
    position: relative;
    width: 80%;
}

#header {
    position: relative;
    height: 50px;
    padding: 10px;
}

You can see it in action here.

The key when using percentage widths and pixel padding/margins is not to define them on the same element (if you want to accurately control the size). Apply the percentage width to the parent and then the pixel padding/margin to a display: block child with no width set.


Update

Another option for dealing with this is to use the box-sizing CSS rule:

#container { 
    -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
    -moz-box-sizing: border-box;    /* Firefox, other Gecko */
    box-sizing: border-box;         /* Opera/IE 8+ */

    /* Since this element now uses border-box sizing, the 10px of horizontal
       padding will be drawn inside the 80% width */
    width: 80%;
    padding: 0 10px;
}

Here's a post talking about how box-sizing works.