Transform makes back side of 3D card unclickable - css

I want to make flip like http://desandro.github.io/3dtransforms/examples/card-01.html
But with buttons on each side. So here is my html
<div class="flip-container">
<div class="flip">
<div class="side front">
<p>front</p>
<button class="front-flip-button">flip</button>
</div>
<div class="side back">
<p>back</p>
<button class="back-flip-button">flip</button>
</div>
</div>
</div>
and css
.flip-container{
position: relative;
-webkit-perspective: 800;
width: 500px;
height: 300px;
}
.flip{
position: absolute;
width: inherit;
height: inherit;
-webkit-transform-style: preserve-3d;
-webkit-transition-duration: 500ms;
-webkit-transform: translate3d(0, 0, 0);
border: 1px solid;
}
.side{
position: absolute;
width: inherit;
height: inherit;
-webkit-transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
}
.flip.flipped,
.back{
-webkit-transform: rotate3d(0, 1, 0, 180deg);
}
.back-flip-button,
.front-flip-button{
position: absolute;
left: 0;
top: 0;
}
p{
font-size: 90px;
text-align: center;
}
And everything is pretty good, but when I use some element with translateZ it makes back button unclickable.
<div class="flip-container">
<div class="flip">
<div class="side front">
<p>front</p>
<button class="front-flip-button">flip</button>
</div>
<div class="side back">
<p>back</p>
<button class="back-flip-button">flip</button>
</div>
</div>
</div>
<div class="some"></div>
Why is that happening?
http://jsfiddle.net/j5Sm4/

Apply this
.back-flip-button {
... Your other styles ...
-webkit-transform:translateZ(1px);
-webkit-backface-visibility:hidden;
/* Needs other prefixes to be cross browser */
}
Demo
This is because the parent element gets its own stacking order. To equalize the stacking order and thus put the button on top, you have to give it a stacking order which I did using translateZ. The backface-visibility:hidden makes the button not show on the front side
In the future we will likely be able to do this by applying the will-change property to the back side

Related

CSS: Determine height of flip card in grid automatically without js

I would like to display two flip cards in a row using grid. Each of the flip cards shall contain a squared image on the front and some text on the back. How can I achieve not having to specify any height within the .flip-card css class? I would like the flip card to automatically adjust its height to the width of the image which itself is dependent on the overall space available within the grid (and therefore changes from device to device). At the moment I have to hardcode the height to make it work. But this inevitably leads the flip card not to be squared but to be a rectangle. Any ideas?
This is my code:
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 20px;
}
.flip-card {
position: relative;
background-color: transparent;
width: 100%;
height: 200px; /* This value should not be hard coded, but be set according to the width of the image which is determined by the grid. It should make the flip card a perfect square*/
overflow: hidden;
perspective: 1000px;
}
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
transition: transform 0.6s;
transform-style: preserve-3d;
}
.flip-card:hover .flip-card-inner {
transform: rotateY(180deg);
}
.flip-card-front, .flip-card-back {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.flip-card-front {
background-color: transparent;
}
.flip-card-back {
background-color: red;
transform: rotateY(180deg);
}
<div class="grid-container">
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front">
<img src="https://upload.wikimedia.org/wikipedia/commons/d/de/Wikipedia_Logo_1.0.png">
</div>
<div class="flip-card-back">
<p>
Some Text
</p>
</div>
</div>
</div>
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front">
<img src="https://upload.wikimedia.org/wikipedia/commons/d/de/Wikipedia_Logo_1.0.png">
</div>
<div class="flip-card-back">
<p>
Some Text
</p>
</div>
</div>
</div>
</div>
Don't use position:absolute to achieve this. Rely on CSS grid and make both the front and the back of the card on the same area so they overlap while still being in flow element so the area will be defined with the biggest height:
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 20px;
}
.flip-card {
overflow: hidden;
perspective: 1000px;
}
.flip-card-inner {
display: grid; /* here */
transition: transform 0.6s;
transform-style: preserve-3d;
}
.flip-card:hover .flip-card-inner {
transform: rotateY(180deg);
}
.flip-card-front,
.flip-card-back {
grid-area: 1/1; /*and here */
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.flip-card-back {
background-color: red;
transform: rotateY(180deg);
}
img {
max-width: 100%
}
<div class="grid-container">
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front">
<img src="https://upload.wikimedia.org/wikipedia/commons/d/de/Wikipedia_Logo_1.0.png">
</div>
<div class="flip-card-back">
<p>
Some Text
</p>
</div>
</div>
</div>
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front">
<img src="https://upload.wikimedia.org/wikipedia/commons/d/de/Wikipedia_Logo_1.0.png">
</div>
<div class="flip-card-back">
<p>
Some Text
</p>
</div>
</div>
</div>
</div>

Skewing a background the opposite way round

I've never felt so silly asking a SO question... but here is goes.
I've created a skew which works a charm, see here
.skewed-bg {
background: #E7ADBB;
padding: 200px 0;
transform: skew(0deg, -7deg);
margin-top: -200px;
z-index: 0;
color: white;
}
.skew-lb {
padding-bottom: 50px !important;
}
.content {
transform: skew(0deg, 7deg);
text-align: center;
}
<div class="skewed-bg skew-lb">
<div class="content">
<div class="container">
<div class="row justify-content-center">
<div class="col-12 col-md-10 text-center">
<h1 class="h1 hero-title mb-3">Everything you need to know about...</h1>
</div>
</div>
</div>
</div>
</div>
But when I try to make the skew the opposite way round, everything just turns into mayhem and I have no idea why this is happening - surely it's just reversing the numbers of the skew around? This is my code...
.skewed-bg {
background: #E7ADBB;
padding: 200px 0;
transform: skew(-7deg, 0deg);
margin-top: -200px;
z-index: 0;
color: white;
}
.skew-lb {
padding-bottom: 50px !important;
}
.content {
transform: skew(7deg, 0deg);
text-align: center;
}
<div class="skewed-bg skew-lb">
<div class="content">
<div class="container">
<div class="row justify-content-center">
<div class="col-12 col-md-10 text-center">
<h1 class="h1 hero-title mb-3">Everything you need to know about...</h1>
</div>
</div>
</div>
</div>
</div>
Can somebody put me out of my misery here? PS- I apologise in advance for being a plonker.
The reason it doesn't work is because skew(ax, ay). If you simply reversed the angles, you would be changing x-axis instead of y-axis. So use an inverse angle instead. 7deg becomes -7deg
Read about skew here.
Do it like this:
.skewed-bg {
background: #E7ADBB;
padding: 200px 0;
transform: skew(0deg, 7deg);
margin-top: -200px;
z-index: 0;
color: white;
}
.skew-lb {
padding-bottom: 50px !important;
}
.content {
transform: skew(0deg, -7deg);
text-align: center;
}
<div class="skewed-bg skew-lb">
<div class="content">
<div class="container">
<div class="row justify-content-center">
<div class="col-12 col-md-10 text-center">
<h1 class="h1 hero-title mb-3">Everything you need to know about...</h1>
</div>
</div>
</div>
</div>
</div>
Here is an example of how you can achieve the same result using :before selector. Less nesting.
.container {
text-align: center;
height: 300px;
width:900px;
position: relative;
overflow: hidden;
margin: 0 auto;
}
.container:before {
content: "";
position: absolute;
background: darkOrange;
height:100%;
width: 200%;
transform: rotate(15deg);
top: -35%;
left: -25%;
z-index: -1;
}
h1 {
z-index: 1;
color: white;
width: 100%;
line-height: 120px;
text-align: center;
}
<div class="container">
<h1>Exmaple </h1>
</div>
Using this method, the text will not be skewed
change the -7 into a 7 in the skew
and for the content flip them over so ts like this skew(0deg, -7deg)
.skewed-bg {
background: #E7ADBB;
padding: 200px 0;
transform: skew(0deg, 7deg);
margin-top: -200px;
z-index: 0;
color: white;
}
.skew-lb {
padding-bottom: 50px !important;
}
.content {
transform: skew(0deg, -7deg);
text-align: center;
}
<div class="skewed-bg skew-lb">
<div class="content">
<div class="container">
<div class="row justify-content-center">
<div class="col-12 col-md-10 text-center">
<h1 class="h1 hero-title mb-3">Everything you need to know about...</h1>
</div>
</div>
</div>
</div>
</div>

z-index issues with Div boxes

Hi when I'm hovering on I want the box to flip 180 and stay z-index'd on top of the boxes behind them. How do I achieve this in order to display on top I set the z-index in hover to 100 but as soon as I hover off it goes behind the boxes. I have tried transition delay as well and I'm still getting the same issue. Can someone help me?
<!DOCTYPE html>
<html>
<head>
<style>
.boxfront {
position: absolute;
display: inline-block;
width: 100px;
height: 100px;
background-color: green;
backface-visibility: hidden;
}
.container {
display: inline-block;
position: relative;
width: 100px;
height: 100px;
background-color: red;
transition-property: transform, z-index;
transition-duration: 2s, 10s;
transition-delay:0s,0s;
transform-style: preserve-3d;
}
.container:hover {
transform: scale(2, 2) rotateY(180deg);
z-index: 100;
}
</style>
</head>
<body>
<div class="container">
<div class="boxfront"></div>
</div>
<div class="container">
<div class="boxfront"></div>
</div>
<div class="container">
<div class="boxfront"></div>
</div>
<div class="container">
<div class="boxfront"></div>
</div>
<div class="container">
<div class="boxfront"></div>
</div>
<div class="container">
<div class="boxfront"></div>
</div>
</body>
</html>
Try this:
.container {
z-index: 100;
}
.container:hover {
z-index: 200;
}
https://jsfiddle.net/uop6ehac/

Chrome CSS bug: "translate3d" inside a rotated element does not obey "overflow: hidden"

Take a look at this CodePen to see what I mean:
.perspective-container {
margin: 50px 0;
perspective: 1000px;
perspective-origin: 0 50%;
}
.card {
border: 10px solid blue;
width: 300px;
height: 300px;
overflow: hidden;
transform: rotateY(-45deg);
}
.card-inner {
width: 300px;
height: 300px;
overflow: hidden;
}
.scroller {
transform: translate(0, -100px);
}
.scroller-3d {
transform: translate3d(0, -100px, 0);
}
.will-change {
will-change: transform;
}
<h1>Incorrect (uses will-change):</h1>
<div class="perspective-container">
<div class="card"><div class="card-inner">
<div class="scroll-container">
<div class="scroller will-change">
<img src="https://images2.pixlis.com/background-image-horizontal-lines-and-stripes-seamless-tileable-grey-black-22hnju.png" />
</div>
</div>
</div></div>
</div>
<h1>Incorrect (uses translate3d):</h1>
<div class="perspective-container">
<div class="card">
<div class="scroll-container">
<div class="scroller-3d">
<img src="https://images2.pixlis.com/background-image-horizontal-lines-and-stripes-seamless-tileable-grey-black-22hnju.png" />
</div>
</div>
</div>
</div>
<h1>Correct (uses neither translate3d or will-change):</h1>
<div class="perspective-container">
<div class="card">
<div class="scroll-container">
<div class="scroller">
<img src="https://images2.pixlis.com/background-image-horizontal-lines-and-stripes-seamless-tileable-grey-black-22hnju.png" />
</div>
</div>
</div>
</div>
I have a rotated element with perspective applied, inside of which I have a 'scrolling' div which is transformed vertically (imagine a magazine page-turn experience with scrolling divs inside each page). I added will-change: transform to the inner div and that broke the outer container overflow: hidden. This seems to be a bug with the Chrome compositor.
Does anyone know of any workarounds? I would like to keep the will-change attribute because it significantly speeds-up animations on mobile Chrome.
Edit: It looks like this is not specific to the will-change property but any property that makes the inner div its own compositing layer. When I remove the will-change property but change the transform to a translate3d that similarly improves performance and exhibits the bug. The only class on the inner div that allows the rotated parent to correctly render overflow: hidden is the one that adds the 2D transform.
Try something like this CodePen:
.container {
margin: 75px 0;
}
.card {
border: 10px solid blue;
width: 300px;
height: 300px;
overflow: hidden;
-webkit-transform: perspective(1000px) rotateY(-45deg);
transform: perspective(1000px) rotateY(-45deg);
-webkit-transform-origin: 0 50%;
transform-origin: 0 50%;
}
.scroller {
-webkit-transform: translate(0, -100px);
transform: translate(0, -100px);
}
.scroller-3d {
-webkit-transform: translate3d(0, -100px, 0);
transform: translate3d(0, -100px, 0);
}
.will-change {
will-change: transform;
}
<h1>Uses will-change:</h1>
<div class="container">
<div class="card">
<div class="scroll-container">
<div class="scroller will-change">
<img src="https://images2.pixlis.com/background-image-horizontal-lines-and-stripes-seamless-tileable-grey-black-22hnju.png" />
</div>
</div>
</div>
</div>
<h1>Uses translate3d:</h1>
<div class="container">
<div class="card">
<div class="scroll-container">
<div class="scroller-3d">
<img src="https://images2.pixlis.com/background-image-horizontal-lines-and-stripes-seamless-tileable-grey-black-22hnju.png" />
</div>
</div>
</div>
</div>
<h1>Uses neither translate3d or will-change:</h1>
<div class="container">
<div class="card">
<div class="scroll-container">
<div class="scroller">
<img src="https://images2.pixlis.com/background-image-horizontal-lines-and-stripes-seamless-tileable-grey-black-22hnju.png" />
</div>
</div>
</div>
</div>
You could play with perspective() and transform-origin values.

3d cube rotation backwards text in div

I have a 3d cube rotation, that happens on hover. Everything works fine except one thing. When you roll over and the cube rotates showing a new side with text....the text is backwards, not sure why this is happening. I have a JS fiddle set up, and any help I can get on this would be great.
http://jsfiddle.net/c3ewZ/6/
html:
This is back
<div class='box-scene col-xs-12 col-sm-3'>
<div class='box'>
<div class='front face'></div>
<div class="side face">
<p>This is back</p>
</div>
</div>
</div>
<div class='box-scene col-xs-12 col-sm-3'>
<div class='box'>
<div class='front face'></div>
<div class="side face">
<p>This is back</p>
</div>
</div>
</div>
<div class='box-scene col-xs-12 col-sm-3'>
<div class='box'>
<div class='front face'></div>
<div class="side face">
<p>This is back</p>
</div>
</div>
</div>
css
body {
margin:0px;
padding:0px;
}
.box-scene {
-webkit-perspective: 700;
height: 180px;
float:left;
z-index: 999;
padding:0px !important;
}
.box-scene:hover .box {
-webkit-transform: rotateY(90deg);
}
.box {
width: 100%;
height: 100%;
position: relative;
-webkit-transform-style: preserve-3d;
-webkit-transition: all 0.4s ease-out;
-webkit-transform-origin: 90px 90px -90px;
}
.face {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: visible;
-webkit-transform-origin: 0 0;
}
.front {
-webkit-transform: rotateY(0deg);
z-index: 2;
background: #d9d9d9;
}
.side {
background: #9dcc78;
-webkit-transform: rotateY(90deg);
z-index: 1;
left: 0px;
}
JS
var resizer = function () {
var width = parseInt($(".box-scene").css("width"));
$(".box").css("-webkit-transform-origin", "center center -" + width / 2 + "px");
};
resizer();
$(window).resize(function () {
resizer();
});
Rotating the panel the other way will fix the mirror imaging of the text.
.box-scene:hover .box {
-webkit-transform: rotateY(-90deg);
}

Resources