13 replies [Last post]
HymanRoth
HymanRoth's picture
Offline
Regular
Last seen: 16 years 51 weeks ago
Joined: 2006-02-17
Posts: 22
Points: 0

Hello everyone. This is my first post.

I've got a simple problem, but I don't think there's a simple answer. All I want to do is to put a box in a box.

Here's the code:

<html>
<head>
<style type="text/css">

#outerbox {position: absolute;
border: 1px solid red;
height: 200px;
width: 200px;
margin:0px;}

#innerbox {position: absolute;
border: 1px solid green;
height: 100%;
width: 100%;
padding:10px;
margin-top: -1px;
margin-left: -1px;}

</style>
</head>
<body>

<DIV id="outerbox">
<DIV id="innerbox">
</DIV>
</DIV>
</body>
</html>

OK, what happens is that the innerbox goes outside the outerbox because the padding gets added to its width. The obvious hack is to hard code the width of the inner box, but I don't want to do this because I want to contruct a layout (EDIT: see a few posts down for an image of the layout) composed of nested boxes where only the size of the outermost box is explicitly specified, and all the inner boxes are sized propotionally. Only the padding (which occurs only in the inner boxes) will be non-proprtional (ie. fixed).

Another solution would be specify the padding and widths of the inner box in proportional terms, for example padding:0.1em and width: 0.8 em. The problem with this (apart from the fact that two em's above refer to different widths) is that, as mentioned above, the layout will contain boxes of different dimensions, but I want the padding to be constant (in pixel terms) across boxes.

What this all boils down to is mixing fixed and proportional values. In an ideal world I would be able to specify the width of innerbox as 100%-20px - but of course this is not possible.

I've been wracking my brains out for a week, but to no avail.

If anyone has any ideas, I'd love to hear them, thanks

Chris..S
Chris..S's picture
Offline
Moderator
Last seen: 10 years 20 weeks ago
Timezone: GMT+1
Joined: 2005-02-22
Posts: 6078
Points: 173

Box in a Box

I think you need to explain your actual design rather than this specific issue, it could well be that a different approach will yield better results.

e.g.

why do you need two boxes, one inside the other separated by a small amount of padding? what particular appearance do you wish to achieve?

if you know the height and width of the outer box and the padding, why can't you calculate the height and width of the inner box, either in your design, in server side scripts or in javascript?

HymanRoth
HymanRoth's picture
Offline
Regular
Last seen: 16 years 51 weeks ago
Joined: 2006-02-17
Posts: 22
Points: 0

Box in a Box

I would say that the context of the problem is largely irrelevant. I have already solved my layout problem by specifying the width of the inner boxes in pixel terms.

What I want work out is why I can't solve the problem the way I wanted to. I think this rather simple problem highlights a deeper issue which goes to the heart of CSS, namely that boxes are flowed 'from the outside in', but the widths of single boxes are calculated from 'the inside out' i.e. the margins and paddings are added to the contents width. I find this EXTREMELY frustrating, and was wondering if I am missing something.

I have only been learning CSS for a week, but since I have a computing background, I don't like hard-coding values unecessarily.

If anyone is interested I can post the full code of my layout, which is fully proportional, apart from this stupid padding bug. By fully proportional, I mean that you specify the size of the layout, and it flows the rest automatically.

Anonymous
Anonymous's picture
Guru

Box in a Box

  1. No doctype = box model troubles.
  2. You're adding the padding to the wrong box.
  3. I'm not so sure padding would affect an absolutely positioned item anyway.
[/]
HymanRoth
HymanRoth's picture
Offline
Regular
Last seen: 16 years 51 weeks ago
Joined: 2006-02-17
Posts: 22
Points: 0

Box in a Box

1. I didn't want to waste space with the full header, but since you asked, here it is:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

2. I am adding padding to the RIGHT box. If I added padding to the outerbox I'd just move to problem up one level, but it wouldn't go away.

3. ?

Just for the record, here's what the hacked layout looks like (image scaled down):

So as to avoid a whole bunch of replies telling me that I just need one block for each layout box (box1, box2 etc...) please bear in mind that the boxes must be nested so that the layout is poroprtional. This layout is actually based on four levels of nesting, but the only pixel values (apart from fixed heights and widths at one nesting level, which is what I'm trying to avoid) are those that specify the size of the outermost box.

Anonymous
Anonymous's picture
Guru

Box in a Box

HymanRoth wrote:

2. I am adding padding to the RIGHT box. If added padding to the outerbox I'd just move to problem up one level, but it wouldn't go away.
Padding is inside of the box that it is attached to, not outside.

Show a link and let's have a look.

HymanRoth
HymanRoth's picture
Offline
Regular
Last seen: 16 years 51 weeks ago
Joined: 2006-02-17
Posts: 22
Points: 0

Box in a Box

The layout code is still local.

When I said 'adding padding to the outerbox" I meant setting the value to >0, which would obviously put the padding INSIDE the box, but it would also make the block wider and higher by twice the padding value.

I should never have mentioned the layout, because the focus is now on the layout, not on the box-in-a-box problem.

My question is really quite straightforward: is there a way of emulating something like:

padding: 10px
width: 100%-20px
height: 100%-20px

That's all I really want to know, thanks.

Tyssen
Tyssen's picture
Offline
Moderator
Brisbane
Last seen: 8 years 16 weeks ago
Brisbane
Timezone: GMT+10
Joined: 2004-05-01
Posts: 8201
Points: 1386

Box in a Box

HymanRoth wrote:
width: 100%-20px
height: 100%-20px

Not without the use of javascript I wouldn't have thought.

How to get help
Post a link. If you can't post a link, jsFiddle it.
My blog | My older articles | CSS Reference

Anonymous
Anonymous's picture
Guru

Box in a Box

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>straight forward</title>
<style type="text/css">

#outerbox {position: absolute;
border: 1px solid red;
height: 200px;
width: 200px;
margin:0px;
}

#innerbox {position: absolute;
border: 1px solid green;
top: 10px;
bottom:10px;
left:10px;
right:10px;
}

</style>
</head>
<body>

<div id="outerbox">
<div id="innerbox">
</div>
</div>
</body>
</html>

Chris..S
Chris..S's picture
Offline
Moderator
Last seen: 10 years 20 weeks ago
Timezone: GMT+1
Joined: 2005-02-22
Posts: 6078
Points: 173

Box in a Box

In your original question your box had a fixed pixel width and height. Are you saying the outer box dimensions are based on %?

Sure forcing a round peg into a square hole won't work. What I am trying to get to is making the hole round or the peg square and to do that we need to understand the whole problem.

If your question is can you use expressions and mixed units to set the dimensions of an element, then the short answer is no.

As a general rule, its easier to set the width on the outer element and the height on the inner element.

For width, by default (auto and inflow) a block element fills its width after its margins and padding are taken into account. For height , by default (auto) an element expands to contain its children adding its own padding and margins on top of their height.

/edit, Triumph unfortunately due to the limitations of a certain popular browser that method won't work for 85% of net users.

Anonymous
Anonymous's picture
Guru

Box in a Box

Chris..S wrote:
/edit, Triumph unfortunately due to the limitations of a certain popular browser that method won't work for 85% of net users.
Yeah.

HymanRoth
HymanRoth's picture
Offline
Regular
Last seen: 16 years 51 weeks ago
Joined: 2006-02-17
Posts: 22
Points: 0

Box in a Box

Triumph wrote:

#innerbox {position: absolute;
border: 1px solid green;
top: 10px;
bottom:10px;
left:10px;
right:10px;
}

Brilliant !!!!!!!!

I was obsessed with widths and didn't realize that I could just offset from the right and bottom borders!

I'm now REALLY happy. It means I can specify the entire layout shown above just by specifying the the dimensions of the outerbox and the relative proportions of the inner boxes.

Thank you VERY much!

HymanRoth
HymanRoth's picture
Offline
Regular
Last seen: 16 years 51 weeks ago
Joined: 2006-02-17
Posts: 22
Points: 0

Box in a Box

Chris..S wrote:
In your original question your box had a fixed pixel width and height. Are you saying the outer box dimensions are based on %?

If you look at the image I posted of the layout, only the size of the outermost box is specfied in pixels. All of the other box heights and widths (box1,2,etc..) are specified as percentages.

I set myself the task of designing this layout as part of my own 'teach yourself CSS' course. I was quite pleased with my progress, until I hit the padding problem which Triumph has now solved very cleverly.

I don't care if I can't use this design (owing to IE), I just set myself the task to learn CSS.

I suppose you could use my layout generator (under Firefox) to build the layout automatically, and then do a screen shot to get all the pixel placings, which could then be hard-coded back into css. The advantage (I think) of my layout is that you don't have to calculate all of the pixel values youself (e.g. if you wanted four columns you just set the width of each to 25%). It also guarantees things line up exactly.

Thanks again for all your help

HymanRoth
HymanRoth's picture
Offline
Regular
Last seen: 16 years 51 weeks ago
Joined: 2006-02-17
Posts: 22
Points: 0

Box in a Box

I have no idea whether anyone is interested, but here is the full code of the layout generator (with Triumph's mod). It's of limited use because it doesn't work with IE6, but I learned a lot writing it.

I haven't validated it, by the way.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Layout Generator</title>
<style type="text/css"> 

/*
Standard layout generator
=========================

This code will generate a proportional layout.
Only the absolute size of the outermost box (#page) needs be specified (in this version only the height is defined)
The subdivisions within #page are expressed in proportional terms.
This means that the layout can be easily re-sized.

The code assumes that all content will be within the innermost boxes.
Given the generic inheritance rules, behaviour may be unpredictable if content
is not inside the innermost boxes (box1_c, box2_c, etc..)

How to define a layout
----------------------
1) Define the width and height of #page
2) Decide on the colour and width of the border (rule #2)
3) Remember that border pixel and margin pixel value must be the same in rule 2
4) Specify the number and height of the ROWS
5) Specify the number and width of the BOXES (within ROWS)

Notes
-----
#page>*      refers to ROWS
#page>*>*    refers to BOXES
#page>*>*>*  refers to CONTENT BOXES

*/

#page 
     {width:   auto;
	height: 800px;
	top:	20px;
	left:	20px;
        right: 20px;}

#page, #page>*, #page>*>*
     {position: absolute;
      border: 2px solid red;
	margin: -2px;}

#page>*, #page>*>*
     {border-right:  none;
      border-bottom: none;
      width:  100%;
      height: 100%;}


/* ROWS - Height defined as a % of #page height */

#row1 {top:    0px;
       height: 20%;}
	
#row2 {top:    20%;
	 height: 70%;}

#row3 {top:    90%;
	 height: 10%;}

/* BOXES - Height defined as a % of ROW height, width as a % of #page height */

#box1    {left:0px; width:20%; }
#box2    {left:20%; width:60%; }
#box3    {left:80%; width:20%; }

#box4    {left:0px; width:20%; } 
#box5L   {left:20%; width:30%; height:65%; }
#box5R   {left:50%; width:30%; height:65%; }
#box6    {left:80%; width:20%; }

#box7    {left:20%; width:60%; height:35%; top: 65% }

#box8	 {left:0px; width:100%;}


/* CONTENT BOXES - The 'padding' is set by top, left, etc.. */

#page>*>*>* 
     {position: absolute;
      top:	  5px;
	left:   5px;
	right:  5px;
	bottom: 5px;
   /* The following are for demo purposes */
	border: 1px dotted green;
	text-align: center;}

</style>

</head>

<body>

<div id="page">
	<div id="row1">

    		<div id="box1"> 
			<div id="box1_c">
        			<p>box1</p>
			</div>
    		</div>
   		<div id="box2">
        		<div id="box2_c">
        			<p>box2</p>
			</div>
    		</div>
    		<div id="box3">
        		<div id="box3_c">
        			<p>box3</p>
			</div>
    		</div>	

	</div>
	<div id="row2">
    		<div id="box4">
        		<div id="box4_c">
        			<p>box4</p>
			</div>
		</div>
    		<div id="box5L"> 
        		<div id="box5L_c">
        			<p>box5L</p>
			</div>
		</div><div id="box5R"> 
        		<div id="box5R_c">
        			<p>box5R</p>
			</div>
		</div>
		<div id="box6">
        		<div id="box6_c">
        			<p>box6</p>
			</div>
    		</div>
		<div id="box7">
			<div id="box7_c">
        			<p>box7</p>
			</div>
		</div>
    	</div>
	<div id="row3">
		<div id="box8">
			<div id="box8_c">
        			<p>box8</p>
			</div>
		</div>
	</div>
</div>


</body> 
</html>