为什么在父元素应用透视效果时,IE10中backface-visibility:hidden不起作用?

52

好的,这里有另一个IE10的问题。问题是在父元素应用透视时,会破坏背面可见性隐藏设置。请参见此示例:http://jsfiddle.net/2y4eA

当你悬停在红色正方形上时,它会绕x轴旋转180度,即使背面可见性被设置为隐藏,背面也会显示出来,至少直到达到180度为止,然后消失。移除透视属性,你会发现它按预期工作,背面根本不可见,但3D效果当然也丢失了。

可以通过将透视应用于transform属性来解决此问题:http://jsfiddle.net/M2pyb 但这会在与transform-origin-z一起使用时引起问题,当z值设为非0值时,整个东西就会“缩放”:http://jsfiddle.net/s4ndv 所以很遗憾这不是一个解决方案。

背面可见性可能是个bug吗?如果是,是否有其他解决方案除了我提到的这个?


1
你尝试过一些老派的方法来修复Internet Explorer吗?我没有使用过v10,但通常更改显示模式,确保它具有布局,使用overflow:hiddenzoom:1z-index:1,添加子元素等等 - 基本上任何可能改变渲染函数的东西...还有将backface-visibility应用于父元素呢?这似乎会让IE将其视为完全独立的3D实体。 - Pebbl
2
你可以通过将背面可见性应用于子对象而不是父对象(即应用变换的相同元素)来使其在IE10中正常工作。请查看以下链接,其中包含两个JSfiddles,一个类似于您描述的内容,另一个修改后解决了该问题:https://dev59.com/z2XWa4cB1Zd3GeqPRedv - BrutalDev
我相信早期版本的Firefox也存在这个问题,即在动画结束之前不会隐藏背面。我还记得早期版本的Chrome在某些情况下也存在此问题,我认为这可能是由于容器上的背面可见性。事实上,因为Chrome和Firefox存在这个问题,我在我的动画中应用了“opacity”特性来隐藏元素,以便在背面要显示时,正面被隐藏。 - user1076821
有趣的想法,但它只适用于纯色背景... - ndm
我回答了你的问题,希望有所帮助 ;) - Dan Ovidiu Boncut
显示剩余7条评论
6个回答

29
我也遇到了这个故障,它肯定是一个故障。
解决方法是在子元素上应用透视变换。我在这里更新了你的fiddle: http://jsfiddle.net/jMe2c/
.item {
    backface-visibility: hidden;
    transform: perspective(200px) rotateX(0deg);
}
.container:hover .item {
    transform: perspective(200px) rotateX(180deg);
}

(另请参见https://dev59.com/z2XWa4cB1Zd3GeqPRedv#14507332中的答案)

我认为这是因为在IE 10中,父元素的3D属性不会传递给子元素。这是一个已知的不支持的功能。请查看http://msdn.microsoft.com/en-us/library/ie/hh673529%28v=vs.85%29.aspx#the_ms_transform_style_property

目前,Internet Explorer 10不支持preserve-3d关键字。您可以通过手动将父元素的变换应用于每个子元素以及子元素的普通变换来解决此问题。

因此,微软建议的解决方案是手动传播您的3D属性。


1
所以我们又见面了,preserve-3d...不幸的是,这个“解决方法”就是我已经发现并在我的问题中提到的。它的问题在于非零的z transform-origin会通过在z轴上缩放或移动项目来破坏它。这似乎是正确的行为,至少其他浏览器的行为相同,但这正是我试图解决的问题 :) - ndm
抱歉,我已经仔细阅读了你的问题,看起来你已经得出了结论。设置非零 z 轴变换原点 应该 可以缩放元素 - 就像你所说,这是跨浏览器的工作方式。你想要创建什么样的效果? - chowey
作为一条注释,过渡效果并不是故障的根源。只需要.container {perspective: 200px}.item {backface-visibility: hidden; transform: rotateX(179deg);,就会忽略背面可见性。换句话说,在父元素中设置透视时,只有使用rotateX(180度)才能使背面可见性起作用。 - chowey
你想要创造什么样的效果?其实是各种不同的效果。我正在构建一个带有3D转场效果的幻灯片,但我一遍又一遍地遇到了这个问题。我已经采用了旋转+平移等方法进行了解决,但这使得动画看起来不同,所以我仍在寻找一种在根本上解决/解决此问题的方法。 - ndm
也许可以用精确的3D变换问题和jsfiddle开始一个新的问题?可以通过每个元素的变换组合来重现任何效果,而不使用根元素。有时这会使事情变得更加复杂,但有时并非如此。我有3D数学方面的经验,我知道这是真的。很遗憾IE不正确地支持背面可见性,但在他们做到之前,解决方法似乎是手动设置每个元素的3D变换,这很复杂。 - chowey
2
所以我过了一段时间又看了一下这个问题,我真的很想知道为什么我花了这么长时间才明白,应用透视引起的移位可以通过将元素在z轴上向-depth/2像素进行移位来轻松补偿。所以我猜透视函数是“解决方法”(尽管在某些情况下存在问题),因此我将把它标记为正确答案,并且稍后还会添加一个工作立方体的示例。 - ndm

7

11
请您在此处描述解决方案,而不仅是提供另一个网站的链接。 - ASGM
经过数小时的挫败,我发现这是唯一(真正跨浏览器)有效的方法。 - Marius Schulz
最终,这在IE 10上真的有效!我也寻找解决方案已经几个小时了。 - DNT
太棒了。它有效!回应Marius的话,这是我迄今为止发现的唯一在所有浏览器上都能正确运行的方法。顺便说一句:在这里展示该方法将更加有帮助,但请不要认为我不感激 ;) - Karl White
1
请注意(特别是@ASGM),此链接的唯一解决方案受版权保护,作者有超出StackOverflow要求的条件以供使用(显示在页面底部)。 - Sablefoste
此外,不幸的是,在IE11上它表现得相当糟糕(至少我的版本是如此)。 - Stijn de Witt

1

我有一个不合逻辑的好解决方案,我尝试了以上所有的解决方案都没有起作用。然而,一个错误却起了作用。当翻转卡片时,我将backface-visibility设置为可见。在IE和Chrome中都有效。

在Chrome中效果更好,IE也可以。

var flipcard = document.getElementsByClassName("flipcard");
var i;

for (i = 0; i < flipcard.length; i++) {
    flipcard[i].addEventListener("click", function() {
        this.classList.toggle("is-flipped");
    });
}
.card_scene {
    width: 180px;
    height: 234px;
    margin: 10px 5px;
    perspective: 600px;
    float:left;
  }

  .flipcard {
    height: 100%;
    transition: transform 1s;
    transform-style: preserve-3d;
    cursor: pointer;
    position: relative; 
  }

  .flipcard.is-flipped {
    transform: rotateY(180deg);
  }

  .flipcard.is-flipped .card__face {
    backface-visibility: visible;                        
}

 .card__face {
    position: absolute;
    max-width: 100%;
    max-height: 100%;
    line-height: 234px;
    backface-visibility: hidden;
  }
  
 

.card__face--front {
 transform: rotateY(0deg);
}

.card__face--back {
 background: white;
 transform: rotateY(-180deg);
 border: 1px solid #CCC; 
 width: 100%;
}

.cardtext {
 margin: 6px;
    font-size:14px;
    line-height: 1.2em;
    display: inline-block;
    width: 100%;
    white-space: pre;
}

.flipcard-breakfloat {
 clear: left;   
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- start of flipcard tempalte -->
<div class="build-only">
<h2>question text here</h2>
<p>Flip the pictures to...</p>
<div>
<div class="card_scene">
<div class="flipcard">
<div class="card__face card__face--front"><picture class="card__image"><img width="180" height="234" id="yui_3_17_2_1_1534724749880_198" src="https://media.gettyimages.com/photos/world-heritage-listed-rainforest-in-dorrigo-national-park-new-south-picture-id936315116" /> </picture></div>
<div class="card__face card__face--back">
<p class="cardtext">** max width of feedback **<br />Add feedback text here use <br />shift+enter for line breaks. <br />don't use just use enter or <br />break will appear below  <br />iamge, and overlay the text. <br />note the class <br />".nsw-td-flipcard-breakfloat" <br />this breaks the float: left so <br /> following text appears <br />as normal <br />Image size is width: <br />"180" height: "234"</p>
</div>
</div>
</div>
<div class="card_scene">
<div class="flipcard">
<div class="card__face card__face--front"><picture class="card__image"> <img width="180" height="234" alt="" src="https://media.gettyimages.com/photos/lonely-single-tree-in-the-field-picture-id680917092" /> </picture></div>
<div class="card__face card__face--back">
<p class="cardtext">** max width of feedback ** <br />Add feedback text here use <br />shift+enter for line breaks. <br />don't use just use enter or <br />break will appear below  <br />iamge, and overlay the text. <br />note the class <br />".nsw-td-flipcard-breakfloat" <br />this breaks the float: left so <br /> following text appears <br />as normal <br />Image size is width: <br />"180" height: "234"</p>
</div>
</div>
</div>
<div class="card_scene">
<div class="flipcard">
<div class="card__face card__face--front"><picture class="card__image"> <img width="180" height="234" alt="" src="https://media.gettyimages.com/photos/old-tree-picture-id173501312" /> </picture></div>
<div class="card__face card__face--back">
<p class="cardtext">** max width of feedback ** <br />Add feedback text here use <br />shift+enter for line breaks. <br />don't use just use enter or <br />break will appear below  <br />iamge, and overlay the text. <br />note the class <br />".nsw-td-flipcard-breakfloat" <br />this breaks the float: left so <br /> following text appears <br />as normal <br />Image size is width: <br />"180" height: "234"</p>
</div>
</div>
</div>
</div>
<div class="flipcard-breakfloat"></div>
</div>
<!-- end of flipcard tempalte -->
<p></p>
<p></p>


1
我建议停止在所有转换元素上设置透视属性与IE作斗争,并开始测试保留3D的支持。我跟随这个人扩展了Modernizr的属性测试:https://coderwall.com/p/qctclg?comment=This+was+awesome%21+And+exactly+what+i+needed.+Thanks%21+ 这样,就可以为IE缺乏的3D变换实现回退,同时开始尝试其他浏览器中更前沿的可能性。
否则IE将使您的代码过于混乱,仍然无法给您相同的可能性-比如旋转多面体3D对象。
仅供参考。

1
我想到的解决方法是添加一个透明度过渡,其时间为0,并延迟你透视过渡的一半。
.container, .item {
    width: 200px;
    height: 200px;
    opacity:1;
}
.container {
    perspective: 200px;
}
.container:hover .item {
    transform: rotateX(180deg);
    opacity:0;
}
.item {
    background-color: #ff0000;
    backface-visibility: hidden;
    transition: transform 3000ms, opacity 0ms 1500ms;
}

1
好主意,但不幸的是不太可靠。当设置为时间的一半时,该项隐藏得太晚了,而当使用一个在正确时刻隐藏它的值(在这种情况下大约为760毫秒)时,当该项旋转回到其原始状态时,它会在错误的时刻显示 :/ - ndm
但是您可以更改悬停时的延迟时间。对于正常状态,它是transition: transform 3000ms,opacity 0ms 760ms,而对于.container:hover .item,则使其transition: transform 3000ms,opacity 0ms 2200m或者根据需要进行调整以使其看起来更好。 - Dan Ovidiu Boncut
那样做不行,必要的延迟取决于转换中的当前位置,即取决于您何时滚动/退出,延迟需要相应地进行调整(如果可能也不切实际),因为转换总是重新启动。 - ndm

0

我在这个jsfiddle中实现了@torbonaut和@chowey提出的解决方案。

HTML

<div id='container'>
<div class='backhide bottom'>bottom</div>
<div class='backhide top'>top</div>
</div>

CSS

  #container, .bottom, .top {
    width: 200px;
    height: 300px;
    position: absolute;
    -webkit-transition: 1.5s ease-in-out;
    -moz-transition: 1.5s ease-in-out;
    -ms-transition: 1.5s ease-in-out;
    -o-transition: 1.5s ease-in-out;
    transition: 1.5s ease-in-out;
  }

  .backhide{

    -moz-backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
  }

  #container:hover .bottom {
    -moz-transform: perspective(800px) rotateY(0);
    -webkit-transform: perspective(800px) rotateY(0);
    transform: perspective(800px) rotateY(0);
  }
  #container:hover .top {
    -webkit-transform: perspective(800px) rotateY(-180deg);
    -moz-transform: perspective(800px) rotateY(-180deg);
    transform: perspective(800px) rotateY(-180deg);
  }

  .bottom {
    background-color: #ff0000;
    -moz-transform: perspective(800px) rotateY(180deg);
    -webkit-transform: perspective(800px) rotateY(180deg);
    transform: perspective(800px) rotateY(180deg);
  }

  .top {
    background-color: #e0e0e0;


    -moz-transform: perspective(800px) rotateY(0deg);
    -webkit-transform: perspective(800px) rotateY(0deg);
    transform: perspective(800px) rotateY(0deg);

  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接