Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IE :before/:after 100% height issues on td

Does anyone have an idea on how to fix an (apparent) IE rendering bug with the :before/:after heights on a td?

From the looks of it, IE seems to only think a :before/:after pseudo element is as tall as the parent's <TD> content inside of it. If <TD> #1 is x2 lines tall w content and <TD> #2 has only x1 line of content, IE will only render the :before/:after height of <TD> #2 to be as tall as x1 line's worth of content.

I created a fiddle example here to better illustrate my problem: http://jsfiddle.net/231gnfpz/ note: I added a red background to the :before/:after to better help visualize my problem in IE

In my example I have a middle <TD> that I applied a :before/:after to try to create a box-shadow to the outside of the specific column. Its an old project so I don't have access to rewrite the entire table, FireFox/Chrome seem to have no issue with this, IE8-11 appear to have the same problem with my :before/:after having a height:100%.

Code:

table {
  background: grey;
  width: 100%;
}
table td {
  text-align: center;
  vertical-align: top;
  background: white;
  padding: 4px;
  width: 33.33%;
  position: relative;
}
.testTD:before {
  box-shadow: -15px 0 15px -15px grey inset;
  content: " ";
  height: 100%;
  left: -15px;
  position: absolute;
  top: 0;
  width: 15px;
  background: Red;
}
.testTD:after {
  z-index: 1;
  box-shadow: 15px 0 15px -15px grey inset;
  content: " ";
  height: 100%;
  right: -15px;
  position: absolute;
  top: 0;
  width: 15px;
  background: Red;
}
<table cellspacing="1" cellpadding "0" border="0">
  <tr>
    <td>test1</td>
    <td class="testTD">test1</td>
    <td>test1</td>
  </tr>
  <tr>
    <td>test2
      <br/>test2
    </td>
    <td class="testTD">test2</td>
    <td>test2</td>
  </tr>
  <tr>
    <td>test3
      <br/>test3
      <br/>test3
    </td>
    <td class="testTD">test3</td>
    <td>test3</td>
  </tr>
</table>
like image 796
user4447070 Avatar asked Jan 12 '15 22:01

user4447070


1 Answers

Resolved: This issue has been resolved in current preview builds of Internet Explorer on Windows 10. You can presently test this from Windows, or Mac OS X via http://remote.modern.ie. If you require IE 11 (and below) support, the proceeding solution should still suffice for you.

Generally speaking, table cells have their dimensions determined largely by their content. In this case, we can see that the pseudo-element results in being equally as tall as the neighboring content within the shared cell container. This is what Internet Explorer understands 100% to mean.

Your pseudo element is positioned absolutely, and constrained by the relatively positioned table cell. It stands to reason then that we would expect the pseudo element to be as tall as the constraining element, rather than the height of its neighboring content. Internet Explorer appears to be making a mistake in judgment here.

If you'd like the same presentation across all browsers, I would suggest the following changes:

  1. Avoid using pseudo elements here, and instead use actual elements (see below)
  2. Cycle over your elements sizing them to their parent element's offsetHeight

So your markup would look like this:

<td class="testTD">
    <span class="bar"></span>
    <!-- content -->
    <span class="bar"></span>
</td>

You would then style them accordingly as you did the original pseudo elements:

.testTD .bar:first-child,
.testTD .bar:last-child {
    display: block;
    background: #F00;
    width: 15px; height: 100%;
    position: absolute; top: 0; z-index: 1;
    box-shadow: -15px 0 15px -15px grey inset;
}

.testTD .bar:first-child {
    left: -15px;
}

.testTD .bar:last-child {
    right: -15px;
}

In Chrome and Firefox you are already set. You don't need to do anything further. However, in Internet Explorer you will need to manually set the heights of these elements. For this reason, we'll condition the following script on the presence of a documentMode property on the document object:

(function () {

  "use strict";

  if ( document.documentMode && document.documentMode < 12 ) {
      var spans = document.querySelectorAll( "span.bar" ),
          count = spans.length;
      while ( count-- ) {
          spans[count].style.height = spans[count].parentElement.offsetHeight + "px";
      }
  }

}());

The end-result should be consistent across all major browsers.

I will file a bug on this internally on interop grounds. If Chrome and Firefox are behaving one way, and Internet Explorer is behaving another, our team should consider the reasons for this being so. I'll add this question to the ticket I open and be sure to update this answer as necessary.

Update following discussion in comments

It was noted in the comments that the original markup could not be changed in this particular case. Scripting was correctly identified as a possible solution here.

(function () {

    "use strict";

    // Get target cells, and create clone-able span element
    var tds = document.querySelectorAll( ".testTD" ),
        span = document.createElement( "span" );
        span.className = "bar";

    // Cycle over every matched <td>
    for ( var i = 0; i < tds.length; i++ ) {

        // Create references to current <td>, and a(fter)/b(efore) clones
        var t = tds[i], a = span.cloneNode(), b = span.cloneNode();

        // Insert cloned elements before/after <td> content
        t.appendChild( a );
        t.insertBefore( b, t.firstChild );

        // If the user is in Internet Explorer, avoid table-cell height bug
        if ( document.documentMode && document.documentMode < 12 ) {
            a.style.height = b.style.height = t.getBoundingClientRect().height + "px";
        }

    }

}());

If you're using jQuery, this could be written more concisely:

(function () {

    "use strict";

    // Create our clone-able element
    var span = $("<span></span>").addClass("bar");

    // Add cloned <span> elements at beginning/end of all .testTD cells
    $(".testTD").prepend( span.clone() ).append( span.clone() );

    // If the user is in Internet Explorer, avoid table-cell height bug
    if ( document.documentMode && document.documentMode < 12 ) {
        $(".testTD .bar").height(function () {
            return $(this).parent().outerHeight();
        });
    }

}());
like image 187
Sampson Avatar answered Oct 02 '22 05:10

Sampson