I want to make an svg picture file containing some “card flip”-style animations, using css with a stylesheet embedded in the svg file. In Chrome, at least two problems may come up, depending on the exact code used: either the front side of the card remains on visible even when flipped, obscuring the backside, or the back side of the card is wrongly positioned. Here is a simplified version of what I'm trying to achieve:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 100 100"
id="svg2"
version="1.1">
<style>
.outmost {
perspective: 100px;
transform-style: preserve-3d;
}
.outer {
transform-style: preserve-3d;
animation: flip 3s infinite alternate;
transform-origin: 50% 50%;
}
/* Front side */
.outer > :nth-last-child(1) {
transform: rotateY(0deg);
}
/* Backside */
.outer > :nth-child(1) {
transform: rotateY(-180deg);
}
/* Both sides */
.outer > * {
backface-visibility: hidden;
<!-- transform-style: preserve-3d; -->
transform-origin: 50% 50%;
}
@keyframes flip {
50% { transform: rotateY(180deg); }
}
</style>
<g class="outmost"> <!-- Container of the card -->
<g class="outer"> <!-- The card itself -->
<rect x="30" y="30" width="40" height="40" fill="red" /> <!-- Back side of the card -->
<rect x="30" y="30" width="40" height="40" fill="green" /> <!-- Front side of the card -->
</g>
</g>
</svg>
This is the picture with bare rects, as in the code above: http://imgh.us/transformorigin_example_1.svg
This is the picture with rects in groups, like so: <g> <rect … /> </g>
:
http://imgh.us/transformorigin_example_2.svg
This displays pretty much correctly in Firefox 44, but is seriously broken in Chrome 48 (both under MS Windows), and I wonder if there is any way to work around that bugginess. (I have already written off the idea of getting it to work in Internet Explorer – the latter does not animate the picture at all, which is much better than a broken animation.)
First off, Chrome does not seem to respect backface-visibility, which kind of ruins the whole card trick: it shows the same card on top all the time; the backside does not become visible. I tried to resolve this by animating the flipping of the front and back sides of the card separately, changing the visibility property of each exactly when the card turns to the other side, but this didn't work very well in either Firefox or Chrome – apparently the timing is not controlled tightly enough, so the two flips do not synchronize.
Second, if I put the rect:s inside groups (which corresponds to realistic usage), it still works in Firefox, but Chrome responds by weirdly offsetting the backside of the card to the left (this appears to be because the original rotation, intended to put the backside in an upside down starting position, makes a rotation around the wrong center – in other words, the translation-origin property does not seem to have gone into effect yet at that stage, or to have done so incorrectly), and then rotating the whole thing around its new center (which however, does seem to be at translation-origin: 50% 50%
of the (mangled) object, as it should, only that one of the parts is now in the wrong position, so the whole effect ends up wrong). Very revolting.
A few things I have tried, to no avail: 1) putting transform-origin: 50% 50%;
inside the declaration blocks marked /* Front side */ and /* Backside */ (so that they are close, code-wise, to the transformation they are supposed to affect); 2) putting the declaration block /* Both sides */ before the /* Front side */ and /* Backside */ blocks; 3) putting style information inside the rect elements (<rect … style=”…” />
); 4) (somewhat desperately) adding -webkit-
prefixes; 5) using -webkit-backface-visibility: visible;-webkit-backface-visibility: hidden;
, i.e., turning visibility on, then off, as in the answer to this question;
6) adding “overflow:visible” to the “outer” group, as suggested in this question;
7) adding in an extra transform:rotateY(0deg);
or transform: translate3d(0,0,0);
, as proposed in the same question.
It is perhaps also interesting to know, that playing around with properties willy-nilly in Chrome's inspector can sometimes neutralize the second problem (incorrect translation-origin), making the two sides of the card end up in the same place, which becomes evident if the cards are semitransparent and contain a shape (but backface-visibility is still wrong), though I haven't been able to discern any pattern in when this happens. This behavior suggests we might in fact be dealing with two distinct bugs here. So far, it only seems possible to achieve this in the inspector, not by making changes to the source.
I have attempted to find information online, but googling things like “chrome backface-visibility bug” or “chrome transform-origin bug” did not really turn up anything of use, over the ideas I have already tried. (It did, however, turn up this ill-boding quote: “Chrome is full of these types of SVG transform bugs.”) There is a bunch of old, somewhat similar stackoverflow questions, but none of the following helped: backface-visibility:hidden bug in chrome, Did -webkit-backface-visibility break today in Chrome?, Webkit backface visibility not working.
Any ideas?