Home > database >  Behavior of `rotate` and `transform: rotate()` properties in CSS 3D Flipper
Behavior of `rotate` and `transform: rotate()` properties in CSS 3D Flipper

Time:09-01

When using the transform: rotateY(180deg) property, text is selectable on both sides of the flipper.

When using the rotate: y 180deg property, the text on the back side is not available for selection, because front div higher than back div.

Is it possible to somehow solve this problem?

const btn = document.querySelector("button");
const flipperInner1 = document.querySelector(".option1 .flipper__inner");
const flipperInner2 = document.querySelector(".option2 .flipper__inner");

btn.addEventListener("click", () => {
  flipperInner1.classList.toggle("flipper__inner--flipped")
  flipperInner2.classList.toggle("flipper__inner--flipped")
})
/* COMMON STYLES */

.flipper {
  inline-size: 300px;
  block-size: 100px;
  perspective: 1000px;
}

.flipper__inner {
  position: relative;
  inline-size: 100%;
  block-size: 100%;
  border: 1px solid #000;
  transform-style: preserve-3d;
  transition: transform 0.3s, rotate 0.3s;
}

.flipper__side {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
}

.flipper__side--front {
  z-index: 2;
}


/* Option 1: transform: rotate(180deg) */

.option1 .flipper__inner--flipped,
.option1 .flipper__side--back {
  transform: rotateY(180deg);
}


/* Option 2: rotate: y 180deg */

.option2 .flipper__inner--flipped,
.option2 .flipper__side--back {
  rotate: y 180deg;
}
<h2>Option 1: transform: rotate(180deg)</h2>
<div >
  <div >
    <div >Front (text is selectable)</div>
    <div >Back (text is selectable)</div>
  </div>
</div>

<h2>Option 2: rotate: y 180deg</h2>
<div >
  <div >
    <div >Front (text is selectable)</div>
    <div >Back (text is NOT selectable, because `front div` higher than `back div`)</div>
  </div>
</div>

<br/>

<button>CLICK TO FLIP BOTH FLIPPERS</button>

CodePudding user response:

use pointer-events so the front text cannot be selected

const btn = document.querySelector("button");
const flipperInner1 = document.querySelector(".option1 .flipper__inner");
const flipperInner2 = document.querySelector(".option2 .flipper__inner");

btn.addEventListener("click", () => {
  flipperInner1.classList.toggle("flipper__inner--flipped")
  flipperInner2.classList.toggle("flipper__inner--flipped")
})
/* COMMON STYLES */

.flipper {
  inline-size: 300px;
  block-size: 100px;
  perspective: 1000px;
}

.flipper__inner {
  position: relative;
  inline-size: 100%;
  block-size: 100%;
  border: 1px solid #000;
  transform-style: preserve-3d;
  transition: transform 0.3s, rotate 0.3s;
}

.flipper__side {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
}

.flipper__side--front {
  z-index: 2;
}


/* Option 1: transform: rotate(180deg) */

.option1 .flipper__inner--flipped,
.option1 .flipper__side--back {
  transform: rotateY(180deg);
}


/* Option 2: rotate: y 180deg */

.option2 .flipper__inner--flipped,
.option2 .flipper__side--back {
  rotate: y 180deg;
}

.flipper__inner--flipped .flipper__side--front {
  pointer-events:none;
}
<h2>Option 1: transform: rotate(180deg)</h2>
<div >
  <div >
    <div >Front (text is selectable)</div>
    <div >Back (text is selectable)</div>
  </div>
</div>

<h2>Option 2: rotate: y 180deg</h2>
<div >
  <div >
    <div >Front (text is selectable)</div>
    <div >Back (text is NOT selectable, because `front div` higher than `back div`)</div>
  </div>
</div>

<br/>

<button>CLICK TO FLIP BOTH FLIPPERS</button>

CodePudding user response:

You could add the following css which puts the back over the front when flipped.

.flipper__inner--flipped .flipper__side--front {
  z-index:-1;
}
  • Related