IE :before/:after 100% 高度问题

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

有没有人知道如何修复 td 上 :before/:after 高度的(明显的)IE 渲染错误?

从外观上看,IE 似乎只认为 :before/:after 伪元素与父元素在其中的 <TD> 内容一样高。如果 <TD> #1 是 x2 行高 w 内容而 <TD> #2 只有 x1 行内容,IE 只会渲染 <TD> #2 的 :before/:after 高度与 x1 行的内容一样高。

我在这里创建了一个 fiddle 示例来更好地说明我的问题:http://jsfiddle.net/231gnfpz/ 注意:我在 :before/:after 中添加了红色背景,以更好地帮助在 IE 中可视化我的问题

在我的示例中,我有一个中间 <TD>,我应用了一个 :before/:after 来尝试在特定列的外部创建一个框阴影。它是一个旧项目,所以我无法重写整个 table,FireFox/Chrome 似乎对此没有问题,IE8-11 似乎与我的 :before/:after 有同样的问题有 height:100%.

代码:

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>

已解决: 此问题已在 Windows 10 上的 Internet Explorer 当前预览版中得到解决。您现在可以从 Windows,或 Mac OS X 通过 http://remote.modern.ie。如果您需要 IE 11(及更低版本)支持,上述解决方案应该仍然足够您使用。

一般来说,table 单元格的尺寸主要由其内容决定。在这种情况下,我们可以看到伪元素导致与共享单元格容器内的相邻内容一样高。这就是 Internet Explorer 理解 100% 的意思。

您的伪元素是绝对定位的,并受相对定位的 table 单元格的约束。按理说,我们希望伪元素与约束元素一样高,而不是其相邻内容的高度。 Internet Explorer 在这里似乎判断失误了。

如果您希望在所有浏览器中使用相同的演示文稿,我建议进行以下更改:

  1. 避免在此处使用伪元素,而是使用实际元素(见下文)
  2. 循环你的元素,将它们的大小调整到它们的父元素的 offsetHeight

因此您的标记将如下所示:

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

然后您可以像处理原始伪元素一样相应地设置它们的样式:

.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;
}

在 Chrome 和 Firefox 中您已经设置好了。你不需要做任何进一步的事情。但是,在 Internet Explorer 中,您需要手动设置这些元素的高度。出于这个原因,我们将在 document 对象上存在 documentMode 属性 条件下设置以下脚本:

(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";
      }
  }

}());

end-result 应该在所有主要浏览器中保持一致。

我将基于互操作性的理由在内部提交一个错误。如果 Chrome 和 Firefox 以一种方式运行,而 Internet Explorer 以另一种方式运行,我们的团队应该考虑造成这种情况的原因。我会将这个问题添加到我打开的工单中,并确保在必要时更新这个答案。

根据评论中的讨论进行更新

评论中指出,在这种特殊情况下无法更改原始标记。此处将脚本正确确定为可能的解决方案。

(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";
        }

    }

}());

如果你使用的是jQuery,这可以写得更简洁:

(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();
        });
    }

}());