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>
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:
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();
});
}
}());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With