Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does changing the positioning of a table-row element from 'static' to 'absolute' back to 'static' result in a permanent height change?

A display: table-row div with height: 75px is nested inside a display: table div with height: 100px

The height of the child is 100px initially with position: static

By changing the positioning of the child element to absolute and then back to static, the height of the child permanently changes from 100px to 75px.

It only occurs if the parent element is a table and the child is a table-row and apparently it's only in WebKit; firefox/IE change back to 100px height but Chrome/Safari don't.

<div id="div1">
    <div id="div2">
        Hello, world!
    </div>
</div>

#div1
{
    display: table;
    height: 100px;
}

#div2
{
    display: table-row;
    height: 75px;
}

Here's the jsfiddle with the example and output of the positioning type/height.

I originally noticed it by messing with CSS properties in the Chrome developer tools, so it's not something specific to jsfiddle or jQuery.

Why does the height permanently change?

like image 204
Mdev Avatar asked Jun 10 '14 23:06

Mdev


1 Answers

The root of the problem lies in the fact that the table and table-row elements have specified heights, but the table height is greater than the table-row height. Since there are no other rows, this will result in undefined behavior. From the spec:

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.

The following is what appears to be happening, at least based on my own observations:

  1. Unless I'm misreading it, every browser seems to be ignoring the paragraph in the spec that specifies how to compute the height of a table-row element, and taking the table height instead.

  2. When you absolutely position the table-row, its computed height changes to the specified 75px, because absolute positioning turns it into a block box and therefore its dimensions are calculated accordingly.

  3. When you return the element to its static position, it reverts to a table-row (as it should), but Chrome/Safari, for some reason, keeps the 75px from when you made it a block box, while other browsers recalculate the height according to the table, again ignoring its specified height.

As this is technically undefined behavior, whether any of the browsers can be said to have buggy or incorrect behavior is debatable. However, I'm going to go out on a limb and say that this could be related to Chrome's tendency to mess up badly at reflows and repaints, since you'd expect a browser to revert all properties and repaint the layout correctly when you undo a single property change — something Chrome is notoriously bad at.


Alternatively, as mentioned in the comments, this may have something to do with anonymous table objects. The spec does not say that an empty table needs to have an anonymous row and cell, but it looks like Chrome could be creating one to replace the table-row when you first position it, but forgetting to remove it after you put it back in.

For example, if you add some bare text as a child of your table, which the browser will then wrap in an anonymous row box per the spec:

<div id="div1">
    Anonymous row
    <div id="div2">
        <p>Hello World!</p>
    </div>
</div>

Every browser will consistently report the height of #div2 as 75px. Presumably, the remaining space is taken up by the anonymous row box, but unfortunately I'm not familiar enough with the CSS table model to comment further.

like image 155
BoltClock Avatar answered Oct 29 '22 16:10

BoltClock