How to control z-index when using perspective and transform? - html

I've read a lot of pages talking about z-index and how transform and perspective destroys his context. I understand why my code isn't working what I don't know is how to make it work (or at least use and alternative).
As you can see on the image, the select menu is being covered by the card below.
Here is a snippet with a reproduction of the issue:
.square { position: relative; width: 100%; padding-bottom: 100%; }
.square>* { position: absolute; width: 100%; height: 100%; }
/* flip */
/* u -> uncontroled / c -> controled */
.flip { perspective: 200em; }
.flip .front, .flip .back {
-webkit-backface-visibility: hidden; -moz-backface-visibility: hidden;
backface-visibility: hidden; position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
}
#supports (-webkit-transform-style: preserve-3d) or (-moz-transform-style: preserve-3d) or (transform-style: preserve-3d) {
.flip .front, .flip .back {
-webkit-transform-style: preserve-3d; -moz-transform-style: preserve-3d; transform-style: preserve-3d; transition: 1s;
}
}
/* -> horizontal */
.flip .front { z-index: 2; transform: rotateY(0deg); perspective: none;}
.flip .back { transform: rotateY(-180deg); }
.flip.u:hover .back, .flip.c.active .back { transform: rotateY(0deg); }
.flip.u:hover .front, .flip.c.active .front { transform: rotateY(180deg); }
/* -> vertical */
.flip.vertical .back { transform: rotateX(-180deg); }
.flip.vertical.u:hover .back, .flip.vertical.c.active .back { transform: rotateX(0deg); }
.flip.vertical.u:hover .front, .flip.vertical.c.active .front { transform: rotateX(180deg); }
.test {
position: absolute; top: 70%; left: 10%; background-color: green;
height: 100px; width: 10px; z-index: 100;
}
<div style="width: 100px; background-color: black">
<div class="square flip u">
<div class="front" style="background-color: blue">
Front
<div class="test"></div>
</div>
<div class="back" style="background-color: red">Back</div>
</div>
<hr >
<div class="square flip u">
<div class="front" style="background-color: blue">Front</div>
<div class="back" style="background-color: red">Back</div>
</div>
</div>
What I need is the <div class="test"> to be displayed in front of all. Like this. But I don't want to set the z-index on the square divs, because they will be placed inside a flex layout Grid.
Is there a way to say to an element to be always rendered in front of all other? No mathers where is he placed or what is happening to the stack context.

Nobody has found a solution over this last years so here you have what I finally did (as an alternative to solve my specific problem):
I just changed the z-index of all child elements, using js, making thos childs that are first having a higher z-index.
var targets = document.getElementsByClassName("invertChildZOrder");
var i;
for (i = 0; i < targets.length; i++) {
target = targets[i];
for (var i = 0; i < target.childNodes.length; i++) {
var childNode = target.childNodes[i];
if (childNode.className == "square flip u") {
childNode.style.zIndex = "" + (target.childNodes.length - i);
}
}
}
.square { position: relative; width: 100%; padding-bottom: 100%; }
.square>* { position: absolute; width: 100%; height: 100%; }
/* flip */
/* u -> uncontroled / c -> controled */
.flip { perspective: 200em; }
.flip .front, .flip .back {
-webkit-backface-visibility: hidden; -moz-backface-visibility: hidden;
backface-visibility: hidden; position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
}
#supports (-webkit-transform-style: preserve-3d) or (-moz-transform-style: preserve-3d) or (transform-style: preserve-3d) {
.flip .front, .flip .back {
-webkit-transform-style: preserve-3d; -moz-transform-style: preserve-3d; transform-style: preserve-3d; transition: 1s;
}
}
/* -> horizontal */
.flip .front { z-index: 2; transform: rotateY(0deg); perspective: none;}
.flip .back { transform: rotateY(-180deg); }
.flip.u:hover .back, .flip.c.active .back { transform: rotateY(0deg); }
.flip.u:hover .front, .flip.c.active .front { transform: rotateY(180deg); }
/* -> vertical */
.flip.vertical .back { transform: rotateX(-180deg); }
.flip.vertical.u:hover .back, .flip.vertical.c.active .back { transform: rotateX(0deg); }
.flip.vertical.u:hover .front, .flip.vertical.c.active .front { transform: rotateX(180deg); }
.test {
position: absolute; top: 70%; left: 10%; background-color: green;
height: 100px; width: 10px; z-index: 100;
}
<div class="invertChildZOrder" style="width: 100px; background-color: black">
<div class="square flip u">
<div class="front" style="background-color: blue">
Front
<div class="test"></div>
</div>
<div class="back" style="background-color: red">Back</div>
</div>
<hr >
<div class="square flip u">
<div class="front" style="background-color: blue">Front</div>
<div class="back" style="background-color: red">Back</div>
</div>
</div>
As you can imagine. This only solves the problem partially. If the square on the botton has another menu but this times droping up instead of down we will have same problem.

I took a different approach. i removed the animation class after the animation finished. I think it is a simpler solution (and I also wasted hours trying to figure out what was going on...)

All I did was moving the div with class .test outside the div with the flipping element.
.square {
position: relative;
width: 100%;
padding-bottom: 100%;
}
.square>* {
position: absolute;
width: 100%;
height: 100%;
}
/* flip */
/* u -> uncontroled / c -> controled */
.flip {
perspective: 200em;
}
.flip .front,
.flip .back {
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
#supports (-webkit-transform-style: preserve-3d) or (-moz-transform-style: preserve-3d) or (transform-style: preserve-3d) {
.flip .front,
.flip .back {
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
transform-style: preserve-3d;
transition: 1s;
}
}
/* -> horizontal */
.flip .front {
z-index: 2;
transform: rotateY(0deg);
perspective: none;
}
.flip .back {
transform: rotateY(-180deg);
}
.flip.u:hover .back,
.flip.c.active .back {
transform: rotateY(0deg);
}
.flip.u:hover .front,
.flip.c.active .front {
transform: rotateY(180deg);
}
/* -> vertical */
.flip.vertical .back {
transform: rotateX(-180deg);
}
.flip.vertical.u:hover .back,
.flip.vertical.c.active .back {
transform: rotateX(0deg);
}
.flip.vertical.u:hover .front,
.flip.vertical.c.active .front {
transform: rotateX(180deg);
}
.test {
position: absolute;
top: 30%;
left: 3%;
background-color: green;
height: 100px;
width: 10px;
z-index: 10;
}
<div style="width: 100px; background-color: black">
<div class="square flip u">
<div class="front" style="background-color: blue">
Front
</div>
<div class="back" style="background-color: red">Back</div>
</div>
<div class="test"></div>
<hr>
<div class="square flip u">
<div class="front" style="background-color: blue">Front</div>
<div class="back" style="background-color: red">Back</div>
</div>
</div>

Related

Simple CSS parallax creates whitespace in Chrome

I'm trying to make a parallax layout for a site. Following a tutorial that has a great end result but is too much for my needs, so I just left the first two layers. But this results in a big white space right below the last layer that I only see en chrome and not firefox but have no idea how to get rid of. Here is a jsfiddle snippet, as you can see it is very little code but I can't find where this could be coming from. Of course the error only shows in this fiddle if you open it in chrome.
/* Parallax base styles
--------------------------------------------- */
.parallax {
height: 500px; /* fallback for older browsers */
height: 100vh;
overflow-x: hidden;
overflow-y: auto;
-webkit-perspective: 300px;
perspective: 300px;
-webkit-perspective-origin-x: 100%;
perspective-origin-x: 100%;
}
.parallax__group {
position: relative;
height: 500px; /* fallback for older browsers */
height: 100vh;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
.parallax__layer {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
-webkit-transform-origin-x: 100%;
transform-origin-x: 100%;
}
.parallax__layer--fore {
-webkit-transform: translateZ(90px) scale(.7);
transform: translateZ(90px) scale(.7);
z-index: 1;
}
.parallax__layer--base {
-webkit-transform: translateZ(0);
transform: translateZ(0);
z-index: 4;
}
.parallax__layer--back {
-webkit-transform: translateZ(-290px) scale(2);
transform: translateZ(-290px) scale(2);
z-index: 3;
}
.parallax__layer--deep {
-webkit-transform: translateZ(-600px) scale(3);
transform: translateZ(-600px) scale(3);
z-index: 2;
}
/* demo styles */
body, html {
overflow: hidden;
}
body {
font: 100% / 1.5 Arial;
}
* {
margin:0;
padding:0;
}
.parallax {
font-size: 200%;
}
/* centre the content in the parallax layers */
.title {
text-align: center;
position: absolute;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
#group1 {
z-index: 5; /* slide over group 2 */
}
#group1 .parallax__layer--base {
background: rgb(102,204,102);
}
#group2 {
z-index: 3; /* slide under groups 1 and 3 */
}
#group2 .parallax__layer--back {
background: rgb(123,210,102);
}
<div class="parallax">
<div id="group1" class="parallax__group">
<div class="parallax__layer parallax__layer--base">
<div class="title">Base Layer</div>
</div>
</div>
<div id="group2" class="parallax__group">
<div class="parallax__layer parallax__layer--back">
<div class="title">Background Layer</div>
</div>
</div>
</div>
I think your expected result is like this.
The tricky things is that you need to set the position of background layer as absolute but not relative. Then you will manage easier.
The reason of your code doesnt work is that the browser may read your background as position relative first, and then your inside div you set it absolute, transform: translateZ(-290px), so that there is a space at the bottom. For another example, just like you set a div height as 600px and then set the padding-bottom as 400px which means the height is 600px, but the actual content will be 200px. You know css is quite stupid.Haha
/* Parallax base styles
--------------------------------------------- */
.parallax {
overflow-x: hidden;
overflow-y: auto;
-webkit-perspective: 300px;
perspective: 300px;
}
.parallax__group {
}
.parallax__layer {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
-webkit-transform-origin-x: 100%;
transform-origin-x: 100%;
}
.parallax__layer--base {
-webkit-transform: translateZ(0);
transform: translateZ(0);
z-index: 4;
}
.parallax__layer--back {
background: rgb(123,210,102);
}
.parallax {
font-size: 200%;
}
/* centre the content in the parallax layers */
.title {
text-align: center;
position: absolute;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
#group1 {
position: relative;
height: 100vh;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
z-index: 5; /* slide over group 2 */
}
#group1 .parallax__layer--base {
background: rgb(102,204,102);
}
#group2 {
z-index: 3;
position: absolute;
width: 100%;
transform: translateZ(-290px) scale(2);
height: 100vh;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
<div class="parallax">
<div id="group1" class="parallax__group">
<div class="parallax__layer parallax__layer--base">
<div class="title">Base Layer</div>
</div>
</div>
<div id="group2" class="parallax__group">
<div class="parallax__layer parallax__layer--back">
<div class="title">Background Layer</div>
</div>
</div>
</div>

Card Flip animation in HTML CSS not working in IE

This card clip HTML component uses just HTML and CSS, it works except on IE11. On IE11, it is slow and laggy. When I remove backface-visibility:hidden, then it works perfectly on IE11 but I obviously need that line.
What potential fixes are there
https://codepen.io/anon/pen/pKWPVb
<div class="card">
<div class="card__side card__side--front">
</div>
<div class="card__side card__side--back ">
</div>
</div>
CSS
.card {
width: 200px;
perspective: 150rem;
-moz-perspective: 150rem;
position: relative;
height: 52rem;
}
.card__side {
border-radius: 3px;
overflow: hidden;
background: #808080;
height: 50rem;
width: 100%;
transition: all 800ms ease;
position: absolute;
top: 0;
left: 0;
backface-visibility: hidden;
}
.card__side--front {
background: red;
z-index: 1;
}
.card__side--back {
transform: rotateY(180deg);
-ms-transform: rotateY(180deg);
}
.card:hover .card__side--front {
transform: rotateY(-180deg);
-ms-transform: rotateY(-180deg);
}
.card:hover .card__side--back {
transform: rotateY(0deg);
-ms-transform: rotateY(0deg);
}
html {
font-size: 5px;
}
Issue in IE is caused with transition.
If using 2 div elements is not necessary to you, I would suggest something like that:
<div class="card">
<div class="card__side card__side--back ">
</div>
</div>
.card {
width: 200px;
perspective: 150rem;
-moz-perspective: 150rem;
position: relative;
height: 52rem;
}
.card__side {
border-radius: 3px;
overflow: hidden;
background: #808080;
height: 50rem;
width: 100%;
transition: all 800ms ease;
position: absolute;
top: 0;
left: 0;
//backface-visibility: hidden;
}
.card__side--back {
transform: rotateY(180deg);
-ms-transform: rotateY(180deg);
-webkit-transform: rotateY(180deg);
}
.card:hover .card__side--back {
transform: rotateY(0deg);
background: red;
-ms-transform: rotateY(0deg);
-webkit-transform: rotateY(0deg);
}
html {
font-size: 5px;
}

How to make card resposive

I'm using boostrap, and I'm making a flipping animation card inside a row (col-lg-12), the problem is that when I resize the screen the card doesn't act "responsive"
.flip {
-webkit-perspective: 800;
perspective: 800;
position: relative;
text-align: center;
}
.flip .card.flipped {
-webkit-transform: rotatey(-180deg);
transform: rotatey(-180deg);
}
.flip .card {
width: 270px;
height: 178px;
-webkit-transform-style: preserve-3d;
-webkit-transition: 0.5s;
transform-style: preserve-3d;
transition: 0.5s;
}
.flip .card .face {
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
z-index: 2;
}
.flip .card .front {
position: absolute;
width: 270px;
z-index: 1;
}
.flip .card .img {
position: relaitve;
width: 270px;
height: 178px;
z-index: 1;
border: 2px solid #000;
}
.flip .card .back {
padding-top: 10%;
-webkit-transform: rotatey(-180deg);
transform: rotatey(-180deg);
}
.inner {
margin: 0px !important;
}
<div id="porosity" class="card">
<div class="face front">
<div class="inner">
<img src="http://placehold.it/100x100" class="img-responsive center-block" alt="">
<p>Porosity</p>
</div>
</div>
<div class="face back">
<div class="inner text-center">
<p>Permeable to fluids, permeable to outside influences.</p>
</div>
</div>
</div>
Full code: https://codepen.io/elunap/pen/rYJEVW
What I'm doing wrong?
If you mean that when you resize screen the flipping card stay at the left while the others stay at center, if you want to make the flipping card stay at center like the others, you have to add margin: auto as follow:
.flip .card {
/* New property added */
margin: auto
}
check the updated CodePen, hope this what you want.

css 3d rotation and enlarge object

I try to rotate the image and enlarge it (preferably to display in the center of the screen) but it does not work.
The second problem is that when an object grows, it is under other objects (z-index does not help).
Any one can help?
.flip-container {
-webkit-perspective: 1000;
}
.flipped {
-webkit-transform: scale(2);
-webkit-transform: rotateY(180deg);
}
.flip-container,
.front,
.back {
width: 350px;
height: 230px;
}
.flipper {
-webkit-transition: 0.6s;
-webkit-transform-style: preserve-3d;
position: relative;
}
.front,
.back {
-webkit-backface-visibility: hidden;
position: absolute;
}
.front {
z-index: -1;
}
.back {
-webkit-transform: rotateY(180deg);
}
<div class="flip-container">
<div class="flipper" onclick="this.classList.toggle('flipped')">
<div class="front">
<img id="services_img" src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-icon.svg?v=6e4af45f4d66">
</div>
<div class="back">
Wszystko za darmo
</div>
</div>
</div>
You can not set 2 transforms like this
transform: scale(2);
transform: rotateY(180deg);
As they are the same property, one will overwrite the other.
instead, concatenate the values
transform: scale(2) rotateY(180deg);
.beneath {
width: 350px;
height: 230px;
display: flex;
align-items: center;
justify-content: center;
}
.txt {
height: 25px;
}
.beneath p {
float: left;
}
.beneath img {
width: 100%;
}
.flip-container img {
width: 100%;
}
.flipped {
transform-origin: center center;
transform: rotateY(180deg) scale(2);
}
.flip-container,
.flipper,
.front,
.back {
width: 350px;
height: 230px;
position: absolute;
top: 0;
left: 0;
}
.flipper {
transition: 0.6s;
}
.front,
.back {
backface-visibility: hidden;
}
.front {
z-index: 1;
}
.back {
transform: rotateY(180deg);
}
<!-- elements beneath - example only -->
<div class="beneath txt">
<p>This is all beneath.</p>
</div>
<div class="beneath">
<img src="http://via.placeholder.com/350x150" />
</div>
<!-- Original -->
<div class="flip-container">
<div class="flipper" onclick="this.classList.toggle('flipped')">
<div class="front">
<img id="services_img" src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-icon.svg?v=6e4af45f4d66">
</div>
<div class="back">
Wszystko za darmo
</div>
</div>
</div>
I'm lost on why it's not working for you. I've adjusted some of the code, but without extensive code, it's hard to determine what might be causing your issues.
I did notice you had a z-index of -1. I'm guessing since you said it didn't make a difference, it's a leftover from trial-and-error.
I took out relative positions, relocated your absolute position, and fixed your z-index.
From what I can tell, it's working. There may be deeper issues in your code.
.beneath {
width: 350px;
height: 230px;
display: flex;
align-items: center;
justify-content: center;
}
.txt {
height: 25px;
}
.beneath p {
float: left;
}
.beneath img {
width: 100%;
}
.flip-container img {
width: 100%;
}
.flipped {
-webkit-transform: scale(2);
-webkit-transform: rotateY(180deg);
}
.flip-container,
.front,
.back {
width: 350px;
height: 230px;
position: absolute;
top: 0;
left: 0;
}
.flipper {
-webkit-transition: 0.6s;
}
.front,
.back {
-webkit-backface-visibility: hidden;
}
.front {
z-index: 1;
}
.back {
-webkit-transform: rotateY(180deg);
}
<!-- elements beneath - example only -->
<div class="beneath txt">
<p>This is all beneath.</p>
</div>
<div class="beneath">
<img src="http://via.placeholder.com/350x150" />
</div>
<!-- Original -->
<div class="flip-container">
<div class="flipper" onclick="this.classList.toggle('flipped')">
<div class="front">
<img id="services_img" src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-icon.svg?v=6e4af45f4d66">
</div>
<div class="back">
Wszystko za darmo
</div>
</div>
</div>

iPhone 6 CSS transition flicker issues

Having CSS transition on two absolutely positioned elements one over another causes them to interfere on iPhone 6 (maybe iOS in general). Taking a close look reveals some flickering during the transition. I've tried various z-index and 3D transform hacks, but without any success so far so I am a bit tilted atm :(
<div class="flip-container c1">
<div class="flipper">
<div class="front"><!-- front content --></div>
<div class="back"><!-- back content --></div>
</div>
</div>
<div class="flip-container c2">
<div class="flipper">
<div class="front"><!-- front content --></div>
<div class="back"><!-- back content --></div>
</div>
</div>
<button onclick="$('.c2').toggleClass('flipped')">btn1</button>
css:
/* entire container, keeps perspective */
.flip-container {
perspective: 1000;
transform-style: preserve-3d;
-webkit-perspective: 1000;
-moz-perspective: 1000;
-ms-perspective: 1000;
perspective: 1000;
-ms-transform: perspective(1000px);
-moz-transform: perspective(1000px);
-moz-transform-style: preserve-3d;
-ms-transform-style: preserve-3d;
margin: 50px auto;
position: absolute;
top: 0;
border: 1px solid grey;
}
/* UPDATED! flip the pane when hovered */
.flip-container.flipped .back {
transform: rotateY(0deg);
}
.flip-container.flipped .front {
transform: rotateY(180deg);
}
.flip-container,
.front,
.back {
width: 320px;
height: 380px;
}
/* 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;
transition: 0.6s;
transform-style: preserve-3d;
position: absolute;
top: 0;
left: 0;
}
/* UPDATED! front pane, placed above back */
.front {
z-index: 2;
transform: rotateY(0deg);
}
/* back, initially hidden pane */
.back {
transform: rotateY(-180deg);
background: lightblue;
}
.c1 .front {
background: lightgrey;
}
.c2 .front {
background: teal;
}
link to an example:
http://codepen.io/AlphaVision/pen/avrVoj