Forum Moderators: not2easy

Message Too Old, No Replies

Box Model and Height 100%

         

Daemn

11:46 am on Jan 2, 2008 (gmt 0)

10+ Year Member



Hi I've spent all night trying to figure this out. Maybe one of the great minds here could point me in the right direction. :)

I have two divs,

<div style="height: 100%; border: 1px solid #000;">
<div style="padding: 10px; background-color: #FFF"></div>
</div>

This makes the parent div 20px more in height. Which would be fine, except the divs are inside a table cell. The table cell does not expand, it allows the div to overflow outside the cell.

Fluid dynamic layout

Example : <snip>

- I can overflow: hidden on the td, but that removes the bottom border and cuts part of it off.
- I can give the parent div min-height: 100% instead of height: 100%, and that kinda works, but the inside div loses it's height 100%, and therefore the background is small and mis-shaped.
- Apparently I can give the td cell padding-bottom: 21px, and the parent div: padding-bottom: 19px, which expands the cell to compensate for the overflow, and such, but that's only if I know, and individually change those values for each section. I'm pretty sure that's impractical for a dynamic layout. If it even works outside of mozilla.

I'm pretty sure I have to use a table for this effect. Gonna change the design, so I can't give the cells a border. It has to be the div inside the cell.

Thanks in advance if anyone lends a hand :)

[edited by: SuzyUK at 12:39 pm (utc) on Jan. 2, 2008]
[edit reason] sorry no personal uri's [/edit]

Daemn

11:52 am on Jan 2, 2008 (gmt 0)

10+ Year Member



Forgot to mention it's an issue in Firefox 2.

The script doesn't work properly in IE. It's just for testing the box model, height 100% in tables in FF2.

Daemn

12:06 pm on Jan 2, 2008 (gmt 0)

10+ Year Member



Okay, script now works almost perfectly in IE. Still overflowing in FF2. Everything is fine except the CSS in FF2.

[edited by: Daemn at 12:24 pm (utc) on Jan. 2, 2008]

SuzyUK

1:09 pm on Jan 2, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi Daemn, Welcome to CSS!

as per stickymail, I tried to summarise your page code but it's heavily javascript dependant and I'm not sure I can even see the issue via that page :o

So based on what you've said in your first post here's some code which I think illustrates the core overflow difference/problem.. let us know - and if it's the right guess, which version would you like to happen IE's or FF's

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Tablesector</title>
<style type="text/css" media="screen, projection">
body {background-color: #000;}
table {background-color: #fff; border: 1px solid #606060; border-collapse: collapse; width: 500px; margin: 0 auto; border: 0;}
td {vertical-align: top; border: 1px solid #0f0; height: 100px;}
p {line-height: 200px; /* to make div overflow */}
.outer {height: 100%; border: 1px solid #000; background: #ff0; padding: 0 30px;}
.inner {padding: 10px; background-color: #ccc;}
</style>
</head>
<body>
<table cellpadding="0" cellspacing="1">
<tr>
<td><div class="outer">
<div class="inner"><p>inner div</p></div>
</div></td>
<td><div class="outer">
<div class="inner"><p>inner div</p></div>
</div></td>
</tr>
</table>
</body></html>

Daemn

11:11 pm on Jan 2, 2008 (gmt 0)

10+ Year Member



Hey SuzyUK, very nice to see you

That's the right guess. Don't need the line-height p to make it overflow though. Here's the example using your code:

Example 1

CSS:
body {background-color: #FFF;}
table {background-color: #0000FF; border-collapse: collapse; width: 500px; margin: 0 auto; border: 0;}
tr {height: 100%;}
td {vertical-align: top; height: 100%;}
p { /* to make div overflow */}
.outer {height: 100%; border: 1px solid #000; background: #ff0; padding: 0 30px;}
.inner {height: 100%; padding: 10px; border: 1px solid #f00; background-color: #ccc;}

HTML:
<table cellpadding="0" cellspacing="0">
<tr>
<td><div class="outer">
<div class="inner">inner div</div>
</div></td>
<td><div class="outer">
<div class="inner">inner div</div>
</div></td>
</tr>
<tr>
<td><div class="outer">
<div class="inner">overflowing div</div>
</div></td>
<td><div class="outer">
<div class="inner">overflowing div</div>
</div></td>
</tr>
</table>

It looks perfect in both IE6 and IE7. In FF2 it looks horrible because the bottom td's overflow. Notice the inner div pops out of the outer div, the td, and the table.

No overflow in IE. Just FF.

-------------------------------------------------------

However, I don't believe you can know if something truly works until you setup the right circumstances, and testing dynamically may be necessary. If you make it static, almost always appears to work, when it may not. This is about to get complicated.

-------------------------------------------------------

The exact same example but with a sibling in each td to increase the height:
Example2

CSS:
body {background-color: #FFF;}
table {background-color: #0000FF; border-collapse: collapse; width: 500px; margin: 0 auto; border: 0;}
td {vertical-align: top; height: 100%;}
tr {height: 100%;}
p { /* to make div overflow */}
.outer {height: 100%; border: 1px solid #000; background: #ff0; padding: 0 30px;}
.inner {height: 100%; padding: 10px; border: 1px solid #FF0000; background-color: #ccc;}
.content {height: 200px; width: 50px;}

HTML:
<table cellpadding="0" cellspacing="0">
<tr>
<td><div class="outer">
<div class="inner">inner div</div>
<div class="content"></div>
</div></td>
<td><div class="outer">
<div class="inner">inner div</div>
<div class="content"></div>
</div></td>
</tr>
<tr>
<td><div class="outer">
<div class="inner">overflowing div</div>
<div class="content"></div>
</div></td>
<td><div class="outer">
<div class="inner">overflowing div</div>
<div class="content"></div>
</div></td>
</tr>
</table>

IE6: Height 100% is not working.
IE7: Height 100% is not working.
FF2: Height 100% is working, but still overflows.

-------------------------------------------------------

Now the reason height 100% does not work in IE6 is because it sets the height of the inside elements before the outside ones, and there is no fixed height for the parent table. Firefox is newer so it knows to update the inside elements after setting the parent elements. IE7 simply won't set a height 100% unless the parent element has a fixed height.

.......
In order to demonstrate this I've used some javascript to remove the height 100%, and add height 100% back again after the loading. It works perfectly in IE6. No problems at all.

<link removed>

IE6: Height 100% is working perfectly. Wow.
IE7: Height 100% is not working.
FF2: Height 100% is working, but still overflows.

------------------------------------
Suzy says: sorry I've cut the post here.. but the next post contains (or will contain) 3 more code samples as is necessary :)
the first two samples should help give a "pointer" to this poser as was requested in OP, if and when this bit is solved there may be more to do - hope that's OK Daemn, there's too much here to deal with in one post ;)
-----------------------------------

[edited by: SuzyUK at 7:42 pm (utc) on Jan. 3, 2008]
[edit reason] entered some code samples, see note [/edit]

SuzyUK

7:50 pm on Jan 3, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi Daemn, and others..

apologies first - this post was taking too long to moderate, and Daemn has summarised the samples well, though they're on external links, so I wanted to to get it so that at least the first two samples could be worked/commented on

The other three summaries will be available as necessary however I think that there is something in this basic code that would benefit from a few sets of eyes.. and that the js problem (if there is one) is a different entity that you Daemn seem to know about since you are capable of adding the code to "help" IE?

sorry of this is way off but time constraints mean I may have done this in a hurry, but check the samples out in Opera then check out what the height attribute is or isn't supported on wrt <table>, <tr>, <td> etc..

I will try to look more later, if I can

Daemn

3:35 am on Jan 6, 2008 (gmt 0)

10+ Year Member



Hmm, could I just leave the first external link so people could see what the overflow looks like in Firefox?

If you have the Firebug addon for Firefox you can edit it directly.

The rest of it was just how I got it to work perfectly in IE, and the only way I believe.

SuzyUK

11:43 am on Jan 6, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hmm, could I just leave the first external link so people could see what the overflow looks like in Firefox?

Sorry Daemn, no links.. :)

The rest of it was just how I got it to work perfectly in IE, and the only way I believe.

This being the CSS Forum, we should be able to tell you if even can work, then if you still need hlp with the JS there is a forum for that.

I still haven't got a chance to look properly yet, but it is very likely that if this is ONLY working in IE, it's not going to be possible in other browsers, it could be that it's an incorrect interpretation by IE that's 'allowing' it to work.

I'm trying to get it back to basics to see if we find the root cause, if we can get it to work without the script, then we will better understand how then to get it to do what you want. Trying to reverse engineer why something works in IE is not the best way to do things in CSS :)

If readers simply paste that first example which I lifted directly from your page they will see the overflow, AND if you check it out in OPERA you will see that the overflow is present on both rows.. the table itself has no height!

I'm sorry I thought someone else would've stepped in to add more help by now - I expect it's to do with height support in tables and also the different table layout models, browsers are given a bit of leeway as to how many passes they take to layout tables so it could be that.. in which case there may be nothing we can do - however I'll take a look now and see what's what

-Suzy

SuzyUK

1:32 pm on Jan 6, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



OK.. here goes nothing

The CSS Table Model [w3.org] is based on the HTML 4.0 table model. Therefore there are certain things that cannot be done no matter the use of CSS.

First off just some very basic observations

  • 1. You would need to set an explicit height for the table, if it's set to 100% what is it 100% of?
  • 2. height inheritance via percentages would only carry through the table IF the entire structure is accounted for. e.g. you would have to account for the <tbody> element -
  • 3. You can't logically set a row height to be 100% then expect 2 or more rows to fit in the table
  • 4. CSS 2.1 does not define what percentage values of 'height' refer to when specified for table cells. 17.5.3 Table height algorithms [w3.org]
  • 5. Tables, being meant for tabular data, will render as best they can so that they contain said data. any dimensioning will only be honoured if the height algorithm can be solved!
  • 6. CSS 2.1 does not define how extra space is distributed when the 'height' property causes the table to be taller than it otherwise would be.

#6 is the important one for your overflow I think, if it's not defined how to distribute extra height, the opposite, overflowing not enough height, is not known either.. this perhaps explains the difference between FF and Opera, FF is solving for the first rows and chooses to only overflow the last row after the data (insert more text in last row to see it grow with text), whereas Opera is overflowing all the table cells because it can't solve the 100% right from the start (imho the 'most' correct interpretation based on the information)!

The core problem is that you cannot use percentage 100% throughout the table structure and expect that the browsers should 'know' to split the rows evenly. 2 rows at 100% of the tables height should = what? - The table rendering model does allow for this, with exceptions - but then if you have your content also set at 100% of a row how should that be dealt with? I forsee browser crashes if they didn't draw the line somewhere!

The second part of the problem, the [.inner] cell has the same height as [outer] which is then increased by the padding, it will or should overflow its parent div [outer] (that's what it's doing in the last row in FF). That overflow should technically be contained by the table cell, but because of the height restrictions on the table elements, the browsers have already laid out the table according to their table layout models and they're not really interested in taking another "pass" to do more maths (when the overflow rule took care of that anyway!).

IE is just being lenient, using a different interpretation of the recommendations - prior to IE7 IE has an "expanding" box problem whereby it doesn't honour fixed heights on any element, it treats a fixed height like min-height - I think that was because it was based on their table model and why it still does in tables. Also this is likely throw back behaviour to tables for layouts hacks, IE behaviour is often what people expect, even though it's been proved that it's not always best, in this case it might be the preferred interpretation, but hopefully some of the random thoughts above show it's not easy to allow for all variations of tables that are not data tables!

Using min-height and height:inherit for newer browsers may be a possibility, I got FF closest, but not right using them but again no go with Opera. I don't think there's anyway to do this without using explicit heights (on the table cells and divs?), but that may not sit the end application..

If you look at your version (with script)¦ in Opera, you will see it looks even more different, it's not even expanding the outer/inner divs to the full cell height, so there is no overflow but instead there are gaps :o

WRT getting the working application fixed, IMHO you will need to get the core heights working in the simple scenarios first before you can script changes to those heights

Haven't checked any other browsers but the differences between, IE6, IE7, FF and Opera would be enough to convince me that another approach may be worth looking into?

-Suzy

SuzyUK

12:08 pm on Jan 10, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi Deamn

I've had a play around with various rules and anomalies, and even found an older thread [webmasterworld.com] with a post which I'd made but forgotten, which gave a clue as to how you might be able to solve it

how you would incorporate it I don't know but it might be possible.
Note, that adding a sibling with 100% height will always cause this to break as it together with anything else will overflow the table cell/inner div, but in your application I believe you are using spacers to prop open the empty cell and then when you click on a cell this toggles the visbility of the sibling, which is to increase the height of that cell, possible solution to this is to toggle/hide the "prop" element so only the sibling is showing, i.e. take it out of the height calculation.

sample code with an attempt and explanation to follow:


CSS:
html, body {margin: 0; padding: 0;}
table {background: blue;
height: 500px; /* this would need to recalculated and reset if content divs require the table to be taller than this */
width: 500px;
margin: 0 auto;
border: 0;
}

tr {height: 50%;} /* for FF, IE and Opera two rows at 50% each e.g. if 3 rows adjust to 33% */
td {
vertical-align: top;
height: 50%; /* for FF to carry on inheritance, same value as tr! */
padding: 10px 0;
}

.outer {
height: 100%;
border: 1px solid #000;
padding: 0 30px;
background: yellow;
}

.inner {
height: 100%;
padding: 10px;
border: 1px solid #FF0000;
/* height is now 100% of 'outer' + 11px top and bottom for the padding and border so compensate with negative margin */
margin: -11px 0;
background-color: #eee;
}
.content {
height: 200px; /* this should be no more than half the table height (for 2 row example) */
/* if it is then this is where the table height recalculation should be made */
margin: 0;
background: #0f0;
}

/* toggle the "c" or "i" class name on the outer div depending on which child to show */
.i .inner, .c .content {display: block;}
.c .inner, .i .content {display: none;}

HTML:
<table cellpadding="0" cellspacing="0">
<tr>
<td><div class="outer i">
<div class="inner">inner div</div><div class="content">content</div>
</div></td>
<td><div class="outer c">
<div class="inner">inner div</div><div class="content">content</div>
</div></td>
</tr>
<tr>
<td><div class="outer i">
<div class="inner">overflowing div</div><div class="content">content</div>
</div></td>
<td><div class="outer i">
<div class="inner">overflowing div</div><div class="content">content</div>
</div></td>
</tr>
</table>

It would perhaps be easier to script changes if you wrapped the table in a div and positioned set the height on the div, allowing the table to always be 100% of the div.

The actual values for % inheritance on the <tr> and <td> will depend on how many rows are in the table 50%, 33%, 25% etc...

the tr/td (same percentage) trick seems to be what keeps all thee of the majors happy, but I'm not sure about Mac browsers..

if the table content causes the outer div to overflow it will crop the content, so the calculations need to adjust the table or containing div's height

In my code, the blue is the actual table cells,
The yellow is the padded inner div which the table will contain as per table formatting recommendations.
The light grey is the inner div and is the one which will overflow/crop the outer div *without* stretching the table cell. I've compensated for the box model padding overflow by giving the equivalent in negative margins so it stays inside the outer div

where I have ".i" and ".c" in the HTML is my attempt at explaining a toggle choice, but again without knowing full application I don't know if it would work for you

this is not a full solution for you but with your knowledge of what you want the script to do, perhaps the couple of x-browser tricks here will help the end goal?