views:

925

answers:

5

Here's a question that's been haunting me for a year now. The root question is how do I set the size of an element relative to its parent so that it is inset by N pixels from every edge? Setting the width would be nice, but you don't know the width of the parent, and you want the elements to resize with the window. (You don't want to use percents because you need a specific number of pixels.)

Edit I also need to prevent the content (or lack of content) from stretching or shrinking both elements. First answer I got was to use padding on the parent, which would work great. I want the parent to be exactly 25% wide, and exactly the same height as the browser client area, without the child being able to push it and get a scroll bar. /Edit

I tried solving this problem using {top:Npx;left:Npx;bottom:Npx;right:Npx;} but it only works in certain browsers.

I could potentially write some javascript with jquery to fix all elements with every page resize, but I'm not real happy with that solution. (What if I want the top offset by 10px but the bottom only 5px? It gets complicated.)

What I'd like to know is either how to solve this in a cross-browser way, or some list of browsers which allow the easy CSS solution. Maybe someone out there has a trick that makes this easy.

A: 

Simply apply some padding to the parent element, and no width on the child element. Assuming they're both display:block, that should work fine.

Dan
You could also add width and height of 100% to the child.
Liam
Height only applies if you have set an absolute height on an ancestor element and a height on all intermediate ancestors.
Jim
A: 

Or go the other way around: set the margin of the child-element.

Floatutorial is a great resource for stuff like this.

roosteronacid
A: 

Try this:

.parent {padding:Npx; display:block;}
.child {width:100%; display:block;}

It should have an Npx space on all sides, stretching to fill the parent element.

EDIT: Of course, on the parent, you could also use

{padding-top:Mpx; padding-bottom:Npx; padding-right:Xpx; padding-left:Ypx;}
Lincoln Johnson
A: 

If you are only concerned with horizontal spacing, then you can make all child block elements within a parent block element "inset" by a certain amount by giving the parent element padding. You can make a single child block element within a parent block element "inset" by giving the element margins. If you use the latter approach, you may need to set a border or slight padding on the parent element to prevent margin collapsing.

If you are concerned with vertical spacing as well, then you need to use positioning. The parent element needs to be positioned; if you don't want to move it anywhere, then use position: relative and don't bother setting top or left; it will remain where it is. Then you use absolute positioning on the child element, and set top, right, bottom and left relative to the edges of the parent element.

For example:

#outer {
    width: 10em;
    height: 10em;
    background: red;
    position: relative;
}

#inner {
    background: white;
    position: absolute;
    top: 1em;
    left: 1em;
    right: 1em;
    bottom: 1em;
}

If you want to avoid content from expanding the width of an element, then you should use the overflow property, for example, overflow: auto.

Jim
+1  A: 

The The CSS Box model might provide insight for you, but my guess is that you're not going to achieve pixel-perfect layout with CSS alone.

If I understand correctly, you want the parent to be 25% wide and exactly the height of the browser display area. Then you want the child to be 25% - 2n pixels wide and 100%-2n pixels in height with n pixels surrounding the child. No current CSS specification includes support these types of calculations (although IE5, IE6, and IE7 have non-standard support for CSS expressions and IE8 is dropping support for CSS expressions in IE8-standards mode).

You can force the parent to 100% of the browser area and 25% wide, but you cannot stretch the child's height to pixel perfection with this...

<style type="text/css">
html { height: 100%; }
body { font: normal 11px verdana; height: 100%; }
#one { background-color:gray; float:left; height:100%; padding:5px; width:25%; }
#two { height: 100%; background-color:pink;}
</style>
</head>
<body>
<div id="one">
<div id="two">
<p>content ... content ... content</p>
</div>
</div>

...but a horizontal scrollbar will appear. Also, if the content is squeezed, the parent background will not extend past 100%. This is perhaps the padding example you presented in the question itself.

You can achieve the illusion that you're seeking through images and additional divs, but CSS alone, I don't believe, can achieve pixel perfection with that height requirement in place.

Carl Camera
That is the conclusion that I've been reaching. I'm using the top/left/bottom/right to offset the edges of the child from the parent, but aside from javascript I think I won't get browser compatibility. Even the javascript requires some juggling.
Mnebuerquo