TD height = total height of contained divs? - html

I can't believe I can't find this question here or on Google - it seems such a dumb one I'm embarrassed to ask, but here goes as it's driving me nuts this morning...
Imagine a single-column, stacked bar chart made with divs like this to look a bit like a thermometer:
<div id="thermo">
<div id="thermored"></div>
<div id="thermogreen"></div>
</div>
#thermo is the containing div, #thermored is the full height background and #thermogreen is the overlay that will be changed to reflect data - in the real world it shows percent complete of a task.
As this stands, it works. However, it needs to work inside a table cell (not my choice - it's a system restriction on the CMS). The problem is that the height of the containing TD is (despite trying fixed heights) the total of the two divs, even though they are positioned relatively and overlayed.
Here's the current css - it's not pretty as I've been trying so many combinations of positioning over the last couple of hours
#thermo{
width:140px;
height:500px;
position:relative;
}
#thermored{
width:50px;
height:100%;
margin-left: 20px;
background-color: red;
}
#thermogreen{
width:50px;
height:280px;
margin-left: 20px;
background-color: green;
position:relative;
bottom: 280px;
float:left;
}
*EDIT For info the issue I'm having is in Chrome and FF - IE(8) sets the TD height they way I want

I think the problem you're having comes from the fact that relative positioning leaves elements in normal flow. Have you tried setting position: absolute; for the inner thermogreen div? Absolute positioning takes elements out of normal flow, and therefore the td tag will only take into consideration the height of your thermo div, which is set to 500px in height. (Edit: you can actually leave thermored with no position attribute. It's set to 100% of the height of the thermo div, meaning no matter what your td will be 500px in height, and you have less CSS to worry about).
Have a look at the jsfiddle I came up with:
http://jsfiddle.net/dgRCu/3/
Does this solve your issue? It seems the td has stayed at 500 pixel height instead of expanding to 700+ now.
I'm not sure what the intended purpose of these divs are so I set bottom: 0; on the thermogreen div since it seems what you want is for the green bar to expand in height while the red bar is the background color.

TD cells will collapse/expand to the size of the 'tallest' height. Using css within the cells are going to cause different issues with different browsers or especially email readers.
So, you have tried:
<tr>
<td height="500"></td>
</tr>
And then, putting those block elements in there? Make the height on the first td cell of your table and make it more than the total of the two divs.
You're floating one so the largest should be forcing the height.

Have you used the Dev Tools in IE to see how the table cells are being rendered? Any chance you can make a jsfiddle.net of just the html table and css code?

Related

Absolutely-positioned table header (th) - which browser is wrong?

This simple table with one absolutely-positioned column renders differently in Firefox (and IE) than in Chrome (and other Webkit-based browsers):
http://jsfiddle.net/WZ6x8/
<div>
<table>
<tr>
<th class="absolute"> </th>
<th> </th>
</tr>
</table>
</div>
* {
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
table-layout:fixed;
}
th {
border: 1px solid black;
width: 100px;
}
.absolute {
left: 0;
position: absolute;
}
div {
margin-left: 100px;
}
Why is there a difference? Which browser is wrong (according to the standard)? How can this be fixed to work on all browsers, without removing the line border-collapse: collapse?
Edit: as noted by #urzeit, "If you specify top: 0; the output in firefox is the same as in chrome." However, there are two issues: first, with multiple rows, top: 0; collapses them all into one; second, the right edge of the absolutely-positioned column extends one pixel too far. You can see both issues at http://jsfiddle.net/WZ6x8/3.
This is caused by rounding issues which are often inconsistent across browsers, and are probably the same ones that plague things like background offsets, percentage calculations and so on.
In a nutshell, the reason why rounding issues come into play is found in section 17.6.2 which, as you may have guessed, describes the collapsing border model:
Borders are centered on the grid lines between the cells. User agents must find a consistent rule for rounding off in the case of an odd number of discrete units (screen pixels, printer dots).
And:
The top border width of the table is computed by examining all cells who collapse their top borders with the top border of the table. The top border width of the table is equal to half of the maximum collapsed top border. The bottom border width is computed by examining all cells whose bottom borders collapse with the bottom of the table. The bottom border width is equal to half of the maximum collapsed bottom border.
Since the border width is 1 pixel, which is an odd number, rounding issues occur when attempting to halve that value. So the question of which browser is wrong — or if any of them are — is debatable.
Unfortunately, because this is a rounding issue, it's not possible to work around this using pure CSS unless through inconceivably elaborate hackery, and very difficult to do so using a script as browsers tend to be inconsistent when reporting decimal/fractional offset values as well (in particular, Firefox, IE and Chrome all report wildly different values for offsetTop of your table-cell and its next sibling).
While I can't offer a solution to your problem, hopefully at least I've helped you understand why browsers are behaving the way they do.
Here's the nitty gritty if you're interested in why the issue ultimately lies in the way the collapsing border model is defined.
Section 9.7 states that if an element is absolutely positioned, then its display is set to block, even if it would otherwise be a table-cell. In all browsers, the computed display for that th is in fact block, so no problem there.
As you've correctly pointed out, the containing block of your table cell is the initial containing block. This removes it from its usual containing block which would otherwise be the table. Section 10.6.4 does add that that if your cell does not have any specified height, top or bottom offsets, i.e. they are all auto, then it should remain in its static vertical position and measurements made accordingly. (Likewise the horizontal position is accounted for in section 10.3.7, however since you've given it left: 0 and width: 100px, it gets shifted to the left edge and its width is as specified, excluding the borders.)
But what is this static vertical position? Because it would ordinarily be display: table-cell if it wasn't absolutely-positioned, the static position, and its corresponding measurements, is determined by its position in the table.
Your given table layout is covered by the following subsections of section 17:
17.5 Visual layout of table contents
17.5.2.1 Fixed table layout
17.6.2 The collapsing border model
Section 17 contains elaborate descriptions on how tables, captions, table-rows and table-cells should be laid out. A lot of it is based on HTML, and certain sections are left vague and/or undefined for various reasons. Fixed table layout is pretty well-defined though, and in this case it is not even relevant.
Section 17.5 says this near the bottom:
The edges of the rows, columns, row groups and column groups in the collapsing borders model coincide with the hypothetical grid lines on which the borders of the cells are centered. (And thus, in this model, the rows together exactly cover the table, leaving no gaps; ditto for the columns.)
And:
Note. Positioning and floating of table cells can cause them not to be table cells anymore, according to the rules in section 9.7. When floating is used, the rules on anonymous table objects may cause an anonymous cell object to be created as well.
Which, of course, has been explained just above.
But if an absolutely-positioned table cell is no longer a cell, what happens?
A "missing cell" is a cell in the row/column grid that is not occupied by an element or pseudo-element. Missing cells are rendered as if an anonymous table-cell box occupied their position in the grid.
So while the actual th box is absolutely positioned, it leaves an anonymous "ghost" cell in its place in order for the table to be rendered properly. This anonymous table-cell is empty and does not inherit the styles from the actual table-cell, so it has no intrinsic width.
However, because the actual table-cell's vertical position is static, it is still affected by how the table is rendered, which brings us to section 17.6.2 on the collapsing border model.
multiple rows - Try this css..
<style>
.absolute {
left: 0;
margin-top: -1px;
border-right:0px;
position: absolute;
}
#media screen and (-webkit-min-device-pixel-ratio:0)
{
.absolute {
margin-top: 0px;
}
}
</style>
Chrome And Firefox Demo Screenshot.
The reason this is happening is because you've specified the entry as absolute, meaning firefox's browser style where it sets the "top" css property to 1px is being used. If you want to avoid this you might be able to use a css reset file which blows away browser-specific default formatting.
As for your issue with setting top:0 resulting in the cells collapsing into each other, that is the correct behavior. Absolute renders in the space of the closest positioned CSS element. Think of it as if the element is no longer in its usual place in the DOM. If the two cells specified as absolute have the same closest positioned parent element (in this case the body) then they would both render relative to the same place with each having the top:0 property which means they would overlap.
I don't think either is wrong, you're just running into the (common) issue of browser styles.
In short ,
There are two problem to me in this problem
a) The first problem is overlapping of left <th> with right <th>
The correct browser is one which overlapp the <th> because
you are firstly giving the outer div margin-right:100px;
the <th> with aboslute property should fit this area, but the extra border of 1px increase the width by 2px(left border + right border) .Hence the overlap is correct
b) The second problem is of top margin for the left element
It can be removed by adding
th{
top:0px;
}
This is because of browser effect to html page

What can cause table columns to end up narrower than their definition?

I've got a CSS rule:
#map td {
border: medium none;
height: 32px;
margin: 0;
padding: 0;
width: 32px;
}
And I have a table inside an element called map. Each cell of the table is supposed to contain an image that's 32x32 pixels in size. But when I render it, either in Firefox or in Chrome, the map grid ends up severely squished under certain circumstances.
Examining it in Firebug, I find that the styles are all applied correctly, with the #map td style as the dominant rule for the cells in question, but when I look at the Computed tab, it gives the width property (under "Box Model") as 14.6167px. If I expand the width node, the only thing under it is: #map td 32 px, so I'm a bit at a loss as to what's causing all of my columns to be so much narrower than 32 px.
I'm sorry that this isn't much to go by, but I'm still fairly new to CSS so I don't know a lot of the right questions to ask. Does anyone know what can cause something like this to happen, and how I can deal with it?
UPDATE: After a bit of experimenting, trying to narrow it down to a simple, reproducible test case, it seems to be that the sidebar div is "squeezing" the main div and there's not enough room, so the browser is making the main one narrower, because when I remove the sidebar, everything goes back to the correct width. So now the question is, how do I set this up so that the width of the table is enforced as described and can't be squeezed by other elements to the side of it?
Keep your td/th with a defined width like you've already done.
For your table, set the layout to fixed, and you'll also have to define a fixed width as well.
table{
table-layout: fixed;
width: 64px;
}

Centering HTML table wider than body

When an HTML table is wider than the page body, it's always left aligned, no matter if you specified a centered alignment. I've a table containing CSS3 gradient buttons, whose size isn't easy to predict (buttons size depends on the font used by the browser). On some browsers this table grows wider than the page body, causing the table to become uncentered related to the page banner.
I've read questions like this: Center table, even if it is wider than parent container stating that the only way of centering tables in this scenario is with Javascript.
But I'd wish to find a solution without javascript. The page design is very simple (just the site logo centered on the header, and an array of big buttons below).
Do you have any suggestion for an easy and elegant solution for this, so that the buttons table is always centered in the page?
http://jsfiddle.net/JQ3qb/
I'm not sure but is, this what you want? You can do it with positioning and then play with left percentage to adjust table.
#test{
border: 1px black solid;
width: 800px;
position:relative;
left: -25%;
text-align:center;
}

4 Column Footer in CSS

I'm developing a 4 column footer in CSS, but after wrestling with this for a few hours there are two things that I cannot achieve.
1) Replicating the padding of the first column in the three subsequent columns
2) Extending the vertical border the entire 250px.
Does anyone have any ideas? Here is my code
http://jsfiddle.net/FdHAR/
The best thing to do here is to add a class, possibly footer-column, that you apply to each of the divs. Then put those four divs in a div with the class footer. Your structure would look something like this:
<div class="footer">
<div class="footer-column" id="footer_column1">...</div>
<div class="footer-column" id="footer_column2">...</div>
<div class="footer-column" id="footer_column3">...</div>
<div class="footer-column" id="footer_column4">...</div>
</div>
Obviously, we need to change the styles foor this to look right.
Padding
Let's address the padding first: all you really have to do is select the class and put some padding-left and padding-right on it. It will automatically apply the same padding to each one that way. Also, to make them appear side-by-side, we need to float them. Something like this will do:
.footer-column {
float: left; // Push the div as far up-left as it can be put
width: 25%; // Make sure to subtract the padding
padding: 10px; // We want padding on all sides to make things look nice
}
Now that that's done, let's fix the borders.
Vertical Borders
This is a bit more difficult, unless you know the overall height of the footer. Either way, we can use the CSS selector :first-child to apply the borders. This should do it:
.footer-column {
...
border-left: 1px solid black; // Whatever border you want goes here.
}
.footer-column:first-child {
border-left: none;
}
If you know the height of the footer, you can force that height, and the border will work just fine.
.footer-column {
...
height: 250px; // Force the box to be 250px tall
}
If you don't know the height of the footer, you'll have to use some other styling and possible javascript. But I'll assume you do since you stated a specific value in the question.
You want to use display: table and display: table-cell: http://jsfiddle.net/FdHAR/3/
1) Add
padding-left: 15px;
to #col2,3,4 moves the text off of the vertical white bar. You may need to play with the value to get the exact spacing you're looking for.
2) add height: 250px; to #container4 to make it the right size.
Caveats: this is after a few minutes of adjusting on safari -- your browser may vary...
Played with this a bit, I think this is closer to what you want and should work well across browsers. I'd recommend a fixed width or a min-width on the footer (<footer> is html5).
jsFiddle
Some constructive feedback:
Try to combine your styles as much as possible. No need to re-write and re-set padding, etc across similar elements.
You had div, inside div, yet were treating them like columns. A simpler approach is to use a list and think of each list item as a column. If you wanted to do divs, then don't put them inside each other.
I like to use em for setting font-size or line-height, but use px for anything else. (personal preference, makes sense since it's a screen you're usually working for)
Try to set only 1 or 2 specific strict sizes and then use percentages of that. A good thought is setting the footer font-size to 1.2em, then the h1 could be font-size 130% and smaller could be 80%. This also works well for width, etc. (each column is 25% of the parent).
a jsFiddle hint, you don't need to put the whole html doc there, just the part you want to fiddle with, same for css and jquery drop the ,.

How to make overflow: hidden really hide content?

Please, look at this example. I intend making horizontal layout with pure html/css, don't bother of old browsers. I made it with display: table technique. But displaying main text containers (light-yellow) became a problem. Each of this has overflow: hidden to prevent vertical scroll. Later, I intend adding some shadow effect at the bottom. Now, I want to make in, for example, 80% height with 10% margin top and bottom. But what I get is container with larger text stretching all parents container (light-green), so 80% of it became too much.
Is there any way to avoid it without javascript?
Maybe I can get text container any height, but with some margin at the bottom. I will appreciate any solution.
Do not use table layouts, table cell divs have a problem setting their width/height and thus will not be able to follow overflow rules.
update the following css properties in your layout.css, this will get you started:
#content{
display:block;
height:90%;
overflow:hidden;
vertical-align:top;
}
#content-inner{
display:block;
height:100%;
vertical-align:top;
}
.article{
display:inline-block;
}
It's still not clear what you want; maybe post a quick sketch?
Anyway, I'd want to avoid the horizontal scrollbar. To do that set #content {
width: 61%;} (based on the rest of the CSS). Currently, in layout.css, #content width is set to 305%.
RE:
#Brock Adam, I mean I want to make div.article-content 80% of screen, not 80% of parent container. I believe this can be achieved by forcing parent div#content be exactly 100% of screen, not more. But I don't know how.
div.article-content currently appears 5 times in the page. Setting it to 80% of the screen will give a page that's at least 400% wider than what the user can see.
Questions:
The first div is ID'd as "header", but it's floated left and only 39% wide. Is this a header (bar at top of of page) or a left, side-bar?
Are the articles supposed to be in 5 tiny columns, on the same row, or are they supposed to be one after another, scrolling down the page?
Again, statements and the semantics of the example page are unclear. Posting a quick sketch of the desired layout will help us help you.