52

Ok, so here's another IE10 glitch. The problem is that applying perspective on parent elements breaks the backface-visibility hidden setting. Please see this fiddle: http://jsfiddle.net/2y4eA

When you hover over the red square it rotates by 180° on the x-axis, and even though the backface-visibility is set to hidden, the backface is shown, at least until the 180° is reached, then it disappears. Remove the perspective property, and you'll see that it works as expected, the backface isn't visible at all, but ofcourse the 3d effect is lost.

It's possible to workaround this problem by applying perspective in the transform property: http://jsfiddle.net/M2pyb But this will cause problems in cojunction with transform-origin-z, when z is set to anything other than 0, the whole thing becomes "scaled": http://jsfiddle.net/s4ndv so unfortunately that's not a solution.

The backface-visibilty thingy is probaly a bug? If so, is there any workaound other than the one i've mentioned?

ndm
  • 59,784
  • 9
  • 71
  • 110
  • 1
    have you tried any of the old-school fixes that often fix Internet Explorer? I've not played around with v10 but normally changing display mode, making sure it hasLayout, using `overflow:hidden`, `zoom:1`, `z-index:1`, add children, - basically anything you can think of that may alter the rendering function used... what about applying `backface-visibility` to the parent too? it seems like maybe IE would treat it as an entirely seperate 3D entity. – Pebbl Sep 27 '12 at 13:30
  • I thought that the layout concept was gone in IE10 at the latest? I hadn't tried that until now, unfortunately it doesn't help, the behaviour doesn't change. Applying backface-visibility to both elements doesn't do anything either. – ndm Sep 27 '12 at 15:01
  • hmm.. yeah I wouldn't be surprised if they had got rid of Layout but as I said these were just guesses as I haven't had the chance to sit down with IE10 yet. That's annoying then :/ good old Internet Explorer as per usual... it is still in-development though so you may find it gets fixed. – Pebbl Sep 27 '12 at 17:34
  • Yep, we'll see... I'm using the RTM version AFAICT, so I guess if anything will be fixed, then with an update, but since IE now seems to have a separate update channel, possible fixes might come a little faster. – ndm Sep 27 '12 at 20:34
  • 2
    You can get it to work in IE10 by applying backface visibility to the child object instead of the parent (the same element that the transform is applied to). Take a look at the following link, it contains two JSfiddles, one similar to what you describe and a modified one that fixes the issue: http://stackoverflow.com/questions/11400317/backside-visibility-not-working-in-ie10-works-fine-in-webkit – BrutalDev Nov 23 '12 at 05:47
  • Thanks for trying to help, but that's not the problem, `backface-visibility` already is applied to the child. I already know the linked question, the example is incorrect, it doesn't specify a unit for the `perspective` value, thus it's being ignored, make it `1000px` and you'll see that the same problem occours there. – ndm Nov 24 '12 at 03:21
  • I believe that earlier versions of Firefox had this same issue, where it would not hide the backface of an animation until the end. I also recall that earlier versions Chrome had this issue in certain instances as well, and I believe it is probably due the backface-visibility being on the container. In fact, because Chrome and Firefox had this issue, I applied the `opacity` trait in my animation to hide the element so when the back was going to show, the front side was hidden. –  Feb 08 '13 at 18:11
  • Did you check this example? - http://jsfiddle.net/reybango/ax2Mc/ – Won Feb 14 '13 at 18:33
  • Yes I did, see 3 comments above. – ndm Feb 15 '13 at 20:14
  • This is kind've crude, but it works: http://jsfiddle.net/4fBuF/ – markasoftware Feb 24 '13 at 00:53
  • Interesting idea, though it only works with solid backgrounds... – ndm Feb 25 '13 at 10:12
  • I posted a new answer to your question :) Hope it helps ;) – Dan Ovidiu Boncut Mar 07 '13 at 14:18

6 Answers6

29

I came up against this glitch too and it is definitely a glitch.

The workaround is to apply the perspective transform on the child element. I updated your fiddle here: http://jsfiddle.net/jMe2c/

.item {
    backface-visibility: hidden;
    transform: perspective(200px) rotateX(0deg);
}
.container:hover .item {
    transform: perspective(200px) rotateX(180deg);
}

(See also answer at https://stackoverflow.com/a/14507332/2105930)

I think it is because in IE 10, parent element 3d-properties do not propagate to the child element. This is a known unsupported feature. Check out http://msdn.microsoft.com/en-us/library/ie/hh673529%28v=vs.85%29.aspx#the_ms_transform_style_property:

At this time, Internet Explorer 10 does not support the preserve-3d keyword. You can work around this by manually applying the parent element's transform to each of the child elements in addition to the child element's normal transform.

So the Microsoft-recommended solution is to propagate your 3d properties yourself, manually.

Community
  • 1
  • 1
chowey
  • 9,138
  • 6
  • 54
  • 84
  • 1
    So we meet again, `preserve-3d`... Unfortunately this "workaround" is what I've already found out and mentioned in my question. The problem with it is that a non-zero z transform-origin breaks it by scaling or shifting the item on the z-axis. This seems to be the correct behaviour, at least other browsers behave the same, however this is the problem I'm trying to work around :) – ndm Mar 04 '13 at 13:51
  • Sorry, I have read your question more carefully, and it looks like you already concluded this. Setting a non-zero z transform origin _should_ scale things - as you say, this is how it works cross-browser. What effect are you trying to create? – chowey Mar 04 '13 at 22:12
  • As a note, the transition is not the source of the glitch. All it takes is `.container {perspective: 200px}` and `.item {backface-visibility: hidden; transform: rotateX(179deg);` and backface-visibility gets ignored. In other words, with the perspective in the parent element, ONLY rotateX(180deg) causes backface-visibility to work. – chowey Mar 04 '13 at 23:04
  • "What effect are you trying to create?" Various effects actually. I was building a slideshow with 3d transitions, and I've stumbled over this problem over and over again. I've used workarounds like rotate+translate instead of only rotate+transform-origin, however this makes the animation look different, and so I'm still looking for a way to fix/work around this problem at its root. – ndm Mar 08 '13 at 17:41
  • Maybe start a new question with the exact 3d-transform question and a jsfiddle? It should be possible to reproduce any effect using a combination of transforms per-element, without using a root element. Sometimes this makes things much more complicated, but sometimes not. I have experience with 3d maths and I know this to be true. It sucks that IE doesn't correctly support the backface-visibility but until they do, the work-around looks to be the complicated one of manually setting the 3d transforms per-element. – chowey Mar 08 '13 at 21:35
  • 2
    So I had a look at this again after some time, and I'm really wondering why it took me so long to get it, the shifting caused by applying perspective can be easily compensated by shifting the elements on the z-axis by `-depth/2` pixels. So I guess the perspective function is the "workaround" to go (even tough it's [problematic in some situations](http://stackoverflow.com/q/17203550/1392379)), and therefore I'll mark this as the right answer, and I'll also add an example of my working cuboid later on. – ndm Jun 20 '13 at 13:10
7

I struggled for hours. this is the only crossbrowser solution that worked for me: http://www.cssplay.co.uk/menu/css3-3d-card.html

torbonaut
  • 71
  • 1
  • 2
  • 11
    It would be great if you could describe the solution here, rather than just linking to another site. – ASGM Apr 07 '13 at 14:13
  • After hours of frustration, I've found this to be the only (truly cross-browser) working method. – Marius Schulz Aug 08 '13 at 13:57
  • Finally, this really works on IE 10 too! I've also been looking for a solution for hours. – DNT Dec 11 '13 at 14:00
  • Great stuff. It works! To echo Marius, this is the only method I've yet found that works correctly across all browsers. Sidenote: showing the method in the answer here would be even more helpful, but don't think I'm ungrateful ;) – Karl White Feb 16 '14 at 02:36
  • 1
    Please note (especially @ASGM), this link only solution is copyrighted, and the author has conditions outside of the requirements of StackOverflow to use (displayed at the bottom of the page). – Sablefoste Feb 08 '16 at 02:24
  • Plus, it's failing miserably on IE11, unfortunately (my version of that, at least). – Stijn de Witt Nov 22 '16 at 11:29
1

A workaround that i would imagine is adding a transition for opacity that has 0 timing and has a delay of half of your perspective transition.

.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;
}
Dan Ovidiu Boncut
  • 3,083
  • 4
  • 25
  • 45
  • 1
    Nice idea, but unfortunately not very reliable. When set to half of the time, the item is hidden way too late, and when using a value that hides it in the right moment (something around 760ms in this case), then it's being shown in the wrong moment when the item rotates back to its original state :/ – ndm Mar 08 '13 at 17:17
  • but you can change the delay when it's on hover. for normal state it is transition: transform 3000ms, opacity 0ms 760ms and for .container:hover .item make it transition: transform 3000ms, opacity 0ms 2200m or as much as it has to make it look good. – Dan Ovidiu Boncut Mar 09 '13 at 22:14
  • That won't work, the neccessary delay depends on the current position in the transition, ie depending on when exactly you roll over/out the delay would need to be adjusted accordingly (which is neither possible nor practicable if it where) because the transition always restarts. – ndm Mar 21 '13 at 15:02
1

I would suggest stop battling IE with the perspective property set on all transformed elements and start testing for support for preserve-3d. I followed this guy to expand Modernizr with a property test: https://coderwall.com/p/qctclg?comment=This+was+awesome%21+And+exactly+what+i+needed.+Thanks%21+

that way, its possible to do a fallback for IE's lacking implementation of 3d transforms, and start playing with the more cutting edge possibilities in the other browsers.

otherwise IE will make your code too messy, and still not give you the same possibilities - like rotating multisided 3d objects.

..just my 2 cents.

Malibur
  • 1,695
  • 5
  • 22
  • 31
1

I have a nice illogical solution, I tried all the solutions above and none worked. However, an error did. I set the backface-visibility to visible when the card is flipped. works in both IE and Chrome.

It works better in Chrome, IE is ok.

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>
Michael
  • 11
  • 2
0

I implemented the solution proposed by @torbonaut and @chowey in this jsfiddle

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

  }
Jon
  • 7,848
  • 1
  • 40
  • 41