Table Row Won't Contain Elements with Position:Absolute

Table row won't contain elements with position:absolute

Apparently, the only pure CSS solution is to set display:block on the tr (including implicitly via use of float). However, this severely breaks table layouts and didn't work out very well for me.

I decided to bite the bullet and wrap the content of the cell in a div, as suggested in these answers:

  • https://stackoverflow.com/a/8312358/398242
  • https://stackoverflow.com/a/7629567/398242
<tr>
<td>
<div style="position:relative">
<button style="position:absolute"></button>
</div>
</td>
</tr>

This still has a disadvantage: since our position:relative element must be inside a table cell, it only works in the last cell of the table row (when the goal is to have the absolute element positioned relative to the entire row, in the top right corner). This also doesn't seem to position the element correctly as seen here: http://jsfiddle.net/QU2zT/25/

This seems to be the best we can do, without abandoning table markup or breaking it's rendering.

Absolute position table cell (td) relative to table row (tr)

The browsers are very strict when it comes to tables. It does not work well when you get out of the scope of how tables are designed to work.

However, you can use a trick with fixed positioning to cheat the browser into not taking in account the missplaced table cell, since it is absolutelly off the normal flow:

  • Add a transform property to the table row, so it will act as a fixed position container. Choose one that will not have any visual impact, like transform: scale(1,1);

  • Set the table cell as position: fixed, and then you can move it relatively to the transformed row:

tr {

position:relative;

transform:scale(1,1);

}

td.last{

position:fixed;

left: 10px;

top: 40px;

}
<table>

<tr>

<td>td 1</td>

<td>td 2</td>

<td class="last">td 3</td>

</tr>

<tr>

<td>td 1</td>

<td>td 2</td>

<td class="last">td 3</td>

</tr>

<tr>

<td>td 1</td>

<td>td 2</td>

<td class="last">td 3</td>

</tr>

</table>

CSS Positioning Absolute within table cells not working in Firefox

Change ID's to classes and also displaying it as blocks fixes it:

http://jsfiddle.net/GchWZ/

It is better and more "proper" to user an inner div though as quoted from this stack overflow post: Does Firefox support position: relative on table elements?

<td>
<div style="position:relative">
This will be positioned normally
<div style="position:absolute; top:5px; left:5px;">
This will be positioned at 5,5 relative to the cell
</div>
</div>
</td>

Firefox ignores absolute positioning in table cells

the element is not a block element.
add to the style display:block, you will get the needed behavior.

absolute positioning inside a table

There are a couple things going on here.

You have this:

td {
/*...*/
vertical-align:bottom;
}

That will push the content of the cells to the bottom.

Also, an absolutely positioned element is removed from the normal flow so it won't contribute to its parent's height:

It is removed from the normal flow entirely (it has no impact on later siblings). An absolutely positioned box establishes a new containing block for normal flow children and absolutely (but not fixed) positioned descendants.

In particular, this means that your div.relative elements have a height of zero but they will still have an upper left corner so your absolute positioning offsets are anchored somewhere.

Then you have <div class="slot hidden"> and the hidden removes the <div> from the layout so you effectively have just this:

<div class="relative"></div> <!-- Height zero -->
<div class="slot"></div> <!-- Height 29px -->

That combined with the vertical-align: bottom means that your second div.absolute will be positioned 5px from the top of the div.slot and that is 25px from the bottom of the table cell.

The first cell works fine because the two visible div.slot elements push the div.relative right to the top of the cell, then the div.absolute is positioned 5px from the top of the div.relative and that is 5px from the top of the table cell.

Unfortunately, adding position: relative to a <td> is a bit dodgy as far as browsers go so you'll need some hackery to get your positioning right while keeping vertical-align: bottom. You could re-structure the <td>s like this:

<td>
<div class="relative">
<div class='absolute'>
<p>A</p>
</div>
</div>
<div class="nonsense">
<div class="slot"></div>
<div class="slot"></div>
</div>
</td>

And the CSS like this:

td{
border:1px solid red;
width:100px;
height:60px;
vertical-align: top;
}

.slot{
width:100px;
height:29px;
background-color:#999;
border:1px dashed blue;
}

.relative {
position:relative;
}
.nonsense {
height: 62px; /* td[height] + 2 for the borders */
display: table-cell;
vertical-align: bottom;
}

.absolute{
position:absolute;
top:5px;
left:5px;
}
.hidden{
display:none;
}

Live example: http://jsfiddle.net/ambiguous/aV4nT/

Or you could use visibility: hidden:

hidden
The generated box is invisible (fully transparent, nothing is drawn), but still affects layout. Furthermore, descendants of the element will be visible if they have 'visibility: visible'.

instead of display: none for your .hidden class:

.hidden {
visibility: hidden;
}

This will leave both div.slot elements taking up space and affecting the layout but only the second one will be seen.

Live example: http://jsfiddle.net/ambiguous/RcdNh/

Position an element over a table-row element

You can get this layout with flexbox

FIDDLE

CSS

#b {
width:100%;
list-style: none;
}
.m {
display: flex;
align-items: center;
align-content: center;
position: relative;
background: #789;
border-top: thin solid #ccc;
}
.u {
width: 100px;
float:left;
opacity:.999;
}
.u:before
{
content: '';
width: 100px;
height: 100%;
display: block;
position: absolute;
top:0;
z-index:-1;
}
.c {
overflow: hidden;
width: calc(100% - 100px);
}

.u:hover:before, .c:hover {
background: yellow;
}
.opener {
width: 16px;
text-align: center;
cursor: pointer;
color: red;

left:0;right:0;
bottom:0;
margin: auto;
z-index: 0;
position: absolute;
}
.opener:before {
content:'▼';
display: block;
}

Using Position Relative/Absolute within a TD?

This is because according to CSS 2.1, the effect of position: relative on table elements is undefined. Illustrative of this, position: relative has the desired effect on Chrome 13, but not on Firefox 4. Your solution here is to add a div around your content and put the position: relative on that div instead of the td. The following illustrates the results you get with the position: relative (1) on a div good), (2) on a td(no good), and finally (3) on a div inside a td (good again).

On Firefox 4

<table>

<tr>

<td>

<div style="position:relative;">

<span style="position:absolute; left:150px;">

Absolute span

</span>

Relative div

</div>

</td>

</tr>

</table>

Contain position: absolute elements inside of a div, so that a position: relative div can be inserted before and after it

This should do what you need:

http://jsfiddle.net/ytVvW/

.container {
width: 866px;
height: 600px;
border: 1px solid #ccc;
position: relative;
}

.item {
width: 274px;
height: 180px;
margin: 5px;
float: left;
border: 1px solid red;
position: absolute;
top: 0;
left: 0;
}

.overlay {
width: 100%;
height: 50px;
background-color: #333;
position: absolute;
float: left;
}

.dropdown {
width: 100%;
height: 40px;
background-color: green;
display: block;
top: 190px;
position: relative;
}

.row {
position: relative;
}

#tl { -webkit-transform: translate3d(0px, 0px, 0px); }
#tc { -webkit-transform: translate3d(290px, 0px, 0px); }
#tr { -webkit-transform: translate3d(580px, 0px, 0px); }
#bl { -webkit-transform: translate3d(0px, 203px, 0px); }

pseudo-element inside table

The issue is that you are positioning the pseudo elements relatively to the tr which leads to undefined behavior:

The effect of 'position:relative' on table-row-group, table-header-group, table-footer-group, table-row, table-column-group, table-column, table-cell, and table-caption elements is undefined.

(http://www.w3.org/TR/CSS2/visuren.html#propdef-position).

Full credit to this answer https://stackoverflow.com/a/8502084/3400962 for finding this out.

This means you can't get the desired result by adding and positioning the pseudo element relatively to the tr.

To achieve the effect you are after, you can add and relatively position multiple pseudo elements to the td instead. The pseudo selectors first-child and last-child can be used to ensure that the box-shadow only applies to the ends of the tr.

table {

border: 1px solid black;

border-spacing: 0;

width: 300px;

}

td {

position: relative;

width: 33%;

}

tr.two td::before,

table.two tr td::before {

background: rgba(255, 200, 0, 0.7);

bottom: 5%;

content: "";

left: 0;

position: absolute;

right: 0;

top: 5%;

z-index: -1;

}

tr.two td:first-child::before,

table.two tr td:first-child::before {

box-shadow: -1em 0 0.2em 0 rgba(255, 200, 0, 0.4);

color: red;

content: "test";

left: 5%;

}

tr.two td:last-child::before,

table.two tr td:last-child::before {

box-shadow: 1em 0 0.2em 0 rgba(255, 200, 0, 0.4);

right: 5%;

}
<table>

<tr>

<td>td1</td>

<td>td2</td>

<td>td3</td>

</tr>

<tr class="two">

<td>td1</td>

<td>td2</td>

<td>td3</td>

</tr>

</table>

<table class="two">

<tr>

<td>td1</td>

<td>td2</td>

<td>td3</td>

</tr>

<tr>

<td>td1</td>

<td>td2</td>

<td>td3</td>

</tr>

</table>


Related Topics



Leave a reply



Submit