I've implemented a 3D flip effect in CSS to allow my div to have a front and back side (shows front by default, back on hover). The flip itself is working great, but there is another div at the end with a smaller height, and I can't seem to figure out how to push this div down past the one that flips. My goal is to have the flip div on a line, and the other image down below it instead of being covered up by the flip div.
And of course since we can't make this too easy, both the flip images and the image in the div below all have to be able to handle variable size images, they will never have set dimensions.
Here's the HTML:
<div class="images">
<div class="flip-container" ontouchstart="this.classList.toggle('hover');">
<div class="flipper">
<div class="front">
<img src="http://www.placehold.it/350x450?text=front">
</div>
<div class="back">
<img src="http://www.placehold.it/350x450?text=back">
</div>
</div>
</div>
<br />
<div class="thumbnails columns-3" style=""><img src="http://www.placehold.it/350x150?text=image"></div>
</div>
And here's the CSS:
div.images {
float: left;
margin-bottom: 1em;
}
/* Flip3D */
/* entire container, keeps perspective */
.flip-container {
perspective: 1000;
}
/* flip the pane when hovered */
.flip-container:hover .flipper, .flip-container.hover .flipper {
transform: rotateY(180deg);
}
.flip-container, .front, .back {
/* width: 100%;
height: 100%;*/
}
/* flip speed goes here */
.flipper {
transition: 0.6s;
transform-style: preserve-3d;
}
/* hide back of pane during swap */
.front, .back {
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
}
/* front pane, placed above back */
.front {
z-index: 2;
/* for firefox 31 */
transform: rotateY(0deg);
}
/* back, initially hidden pane */
.back {
transform: rotateY(180deg);
}
Here's my fiddle: https://jsfiddle.net/8z2vbcrw/
Hopefully this all makes sense, but please ask me for clarification if not.
It can be done either by giving a height and width to your .flipper container or by just getting rid of absolute positioning on the front card...
https://jsfiddle.net/8z2vbcrw/
.front, .back {
backface-visibility: hidden;
top: 0;
left: 0;
}
.back {
position: absolute;
}
By doing this, the front card maintains the layout.
Related
I was trying to implement the paper flip transition using css, so in order to achieve that the tasks that I needed were:
I had to move the div from the current position to the left. I was able to achieve it using translate property.
I also had to flip the div. I was able to achieve it using scaleX(-1)
Finally I had to flip it in curve.
How can I achieve the final part? Here is a link to CSSDesk. I have tried the flip transition using hover.
I don't know if it's what ou were looking for, but here is a quick example :
/* entire container, keeps perspective */
.flip-container {
perspective: 1500px;
margin: 0 auto;
margin-top:100px;
}
/* flip the pane when hovered */
.flip-container:hover .flipper, .flip-container.hover .flipper {
transform: rotateY(180deg);
}
.flip-container, .front, .back {
width: 320px;
height: 480px;
}
/* flip speed goes here */
.flipper {
transition: 0.6s;
transform-style: preserve-3d;
transform-origin: 100%;
position: relative;
}
/* hide back of pane during swap */
.front, .back {
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
}
/* front pane, placed above back */
.front {
background-color:red;
z-index: 2;
/* for firefox 31 */
transform: rotateY(0deg);
}
/* back, initially hidden pane */
.back {
background-color:green;
transform: rotateY(180deg);
}
<div class="flip-container" ontouchstart="this.classList.toggle('hover');">
<div class="flipper">
<div class="front">
<p>FRONT</p>
</div>
<div class="back">
<p>BACK</p>
</div>
</div>
</div>
The key to acheive 3d effect is perspective: 1500px;
This example is based on this amazing article which explain the property
I have a grid of divs set up with display: inline-block. When I 3d-rotate them along the y-axis, part of the div leaves the bounds of the resting div so it overlaps with the other adjacent divs.
In firefox it works perfectly, the part of the div closest in the viewers perspective is taller and is visible on top of the adjacent divs.
But in Chrome, the bottom edge of the div is behind the div below. Am i missing something?
HTML
<div class="flip-container">
<div class="flipper">
<div class="front">
<div style="background-color:red;height:162px;width:343px"> front</div>
</div>
<div class="back">
<div style="background-color:red;height:162px;width:343px"> back</div>
</div>
</div>
</div>
<div class="flip-container">
<div class="flipper">
<div class="front">
<div style="background-color:blue;height:162px;width:343px"> front</div>
</div>
<div class="back">
<div style="background-color:blue;height:162px;width:343px"> back</div>
</div>
</div>
</div>
CSS
.flip-container {
-webkit-perspective: 1000;
transform: perspective(1000px);
transform-style: preserve-3d;
display:inline-block;
}
/* flip the pane when hovered */
.flip-container:hover .flipper {
transform: rotateY(180deg);
}
.flip-container, .front, .back {
width: 343px;
height: 162px;
}
/* flip speed goes here */
.flipper {
transition: 6s;
transform-style: preserve-3d;
position: relative;
}
/* hide back of pane during swap */
.front, .back {
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
}
/* front pane, placed above back */
.front {
z-index: 2;
/* for firefox 31 */
transform: rotateY(0deg);
}
/* back, initially hidden pane */
.back {
transform: rotateY(180deg);
}
jsfiddle
Mousing over the divs will slowly rotate so you can see the overlap
Give all the Divs a separate id. eg- red , blue , green
Use javascript to change z-index on hover.
Here is an example : (do it for all 3)
document.getElementById('blue').hover.style.zIndex = document.getElementById('red').style.zIndex + document.getElementById('green').style.zIndex + "1";
This will set the z-index of div on hover to 1 more than the z-index of other 2 Divs.
I am sure there is a more efficient way. Try to experiment with it, may be make a function that on hover on any element of a specific class would make its z-index greater than all. But this will work too.
edit: Don't forget to make their position relative
So ive been struggling with this set of code for a while now and I am so close to finishing it.
First problem was getting my images to be responsive to height and width, but after some discussions I was able to figure out how to make it responsive by simplifying the code and using colors as placeholders but now I cant figure out how to re-add the background images.
Here is the OG codepen, http://codepen.io/anon/pen/YypXjw
and here it is now, http://codepen.io/anon/pen/rOWXzW
* { color: #fff; }
.flip-container {
width: 33.333%;
padding-bottom: 33.333%;
float: left;
}
.flip-container:hover .flipper {
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
}
.flipper {
-webkit-transition: 0.6s;
-webkit-transform-style: preserve-3d;
transition: 0.6s;
transform-style: preserve-3d;
position: relative;
}
.front {
position: absolute;
width: 100%;
padding-bottom: 100%;
}
.front-a {
background: red;
}
.front-b {
background: blue;
}
.front-c {
background: green;
}
I have no idea why I cant get the html to show up as well.
So the code was cleaned up, and now all I need to figure out is how to add a front and back image to the flipping div.
Ive attempted to add front and back divs like the og code but still cant get it to work.
Any help or suggestions is greatly appreciated.
Codepen
You need the front and back classed divs. You can target the front/back of each using pseudo selectors.
<div class="flip-container">
<div class="flipper">
<div class="front"></div>
<div class="back"></div>
</div>
</div>
Background size cover and then each front/back's image.
.front, .back {
background-size: cover;
}
.flip-container:nth-of-type(1) .front {
background-image: url(image.jpg);
}
.flip-container:nth-of-type(1) .back {
background-image: url(image.jpg);
}
http://jsfiddle.net/RtTPU/
I am trying to swap the image "Adam" to "Adam-flipped" on hover, so once the image is hovered over it will swap as it's flipped yet it's not working. Is it possible to do this entirely in CSS?
<div class="flip-container" ontouchstart="this.classList.toggle('hover');">
<div class="flipper">
<div class="front">
<img src="http://adamginther.com/assets/img/adam.jpg" alt="Adam">
</div>
<div class="back">
<img src="http://adamginther.com/assets/img/adam-flipped.jpg" alt="Adam" >
</div>
</div>
</div>
.self-portrait {
border-radius: 400px;
width: 50%;
}
/* entire container, keeps perspective */
.flip-container {
perspective: 1000;
}
/* flip the pane when hovered */
.flip-container:hover .flipper, .flip-container.hover .flipper {
transform: rotateY(180deg);
}
.flip-container, .front, .back {
width: 320px;
height: 480px;
}
/* flip speed goes here */
.flipper {
transition: 0.6s;
transform-style: preserve-3d;
position: relative;
}
/* hide back of pane during swap */
.front, .back {
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
}
/* front pane, placed above back */
.front {
z-index: 2;
}
/* back, initially hidden pane */
.back {
transform: rotateY(180deg);
}
Your code does not work because it lacks the prefixes for transform and backface-visibility. Plus you have to tell the children of .flipper to retain the 3d transforms applied to it and calculate the combined effects automatically by transform-style: preserve-3d (needs prefixes, too).
A second problem: You have to set an explicit width on .flip-container or .flipper to ensure the image flips around the center y axis. Leaving it on auto results in different levels of quirkyness on different screen sizes, though.
Note that my code samples contain only the webkit prefix for brevity. Hope this gets the point across.
Relevant changes:
.flip-container {
...
width: 400px;
height: 400px;
}
.flip-container:hover .flipper {
-webkit-transform: rotateY(180deg);
}
.flipper {
...
-webkit-transform-style: preserve-3d;
height: 100%;
width: 100%;
}
.front, .back {
...
-webkit-backface-visibility: hidden;
}
.back {
-webkit-transform: rotateY(180deg);
}
See all the changes on the fixed version of your fiddle: http://jsfiddle.net/marionebl/RtTPU/6/
Version with less verbose markup and sanitized css styles: http://jsfiddle.net/marionebl/6Je6r/1/
I think here is all you want. fiddle
.flip-container:hover .back{
z-index : 10;
}
.back{
z-index:0;
}
You need prefixes for the transform property.
Also .flip-container.hover is useless, and perspective needs units:
/* entire container, keeps perspective */
.flip-container {
-webkit-perspective: 1000px;
perspective: 1000px;
}
/* flip the pane when hovered */
.flip-container:hover .flipper {
transform: rotateY(180deg);
-webkit-transform: rotateY(180deg);
}
corrected fiddle
Example code here:
http://jsfiddle.net/gat5S/1/
I want to create a "card" that can be flipped via CSS rotateY. The rotation is based on David Walsh's CSS Flip Animation and in principle works well.
However, in my example, I have an :after pseudo-element for each side of the card that I use to create a paper-like shadow effect. This pseudo-element is put behind the card via negative z-index:-1;. This works for the "front" card but not after rotation and not for the "back" card.
The jsFiddle example code shows my problem (currently only containing webkit prefixes). In the initial state everthing looks as intended. The :after pseudo-element saying "INVISIBLE" is only partly visible. When you flip the card via the toggle button two things happen:
The front card :after element becomes visible. This is not intended.
The back card :after element is visible but also in the box where z-index:-1; should make it invisible. Also not intended.
I managed to solve 1. by using JavaScript to add a class to the .front which changes the visibility of :after. However, I cannot manage to solve 2. I tried different z-index values but these don't seem to have any effect at all.
I wonder if there is a clever way to solve both problems. Any help appreciated!
I've got it working
demo
CSS
.front, .back {
text-align: center;
background-color: #FFF9EC;
}
.front:after {
content: ' INVISIBLE ';
position: absolute;
width: 40%;
height: 10px;
left: 70px;
bottom: 12px;
z-index: -1;
-webkit-transform: translateZ(-1px);
-webkit-backface-visibility: hidden;
}
.back:after {
content: ' INVISIBLE ';
position: absolute;
width: 40%;
height: 10px;
left: 70px;
bottom: 12px;
z-index: -1;
-webkit-transform: translateZ(-1px);
-webkit-backface-visibility: hidden;
}
.flip-container {
-webkit-perspective: 1000;
}
/* flip the pane when hovered */
.flip-container.flip .flipper {
-webkit-transform: rotateY(180deg);
}
.flip-container, .front, .back {
width: 100px;
height: 100px;
}
/* flip speed goes here */
.flipper {
-webkit-transition: 0.6s;
-webkit-transform-style: preserve-3d;
position: relative;
left: 30px;
}
/* hide back of pane during swap */
.front, .back {
-webkit-backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
}
.back h1 {
-webkit-backface-visibility: hidden;
}
/* back, initially hidden pane */
.back {
-webkit-transform: rotateY(180deg) translateZ(1px);
-webkit-transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
}
Mainly, I have changed the z-index to translateZ; that is the way you should work in 3D.
There was also some issue with the backface visibility : hidden not propagating to the child elements.