Conjugation · 3rd grade
The pronoun die
Conjugate finir in the present tense with the pronoun on the front face.
Your answer:
Turn the die with the mouse, a finger or the arrow keys.
A 100 px CSS cube with six translucent, colored, labeled faces, set at a three-quarter angle, turns toward the pointer as soon as it enters its area, then goes back to its pose when it leaves. It can also be turned with a finger and with the keyboard's arrow keys; hidden faces show through the others. 1.8 KB of JavaScript, one cube per copy, and no tilt following the pointer when the user reduces motion.
Updated
This effect is free — the 3D category contains 50 effects total, including 8 free. Effect.Labs has 840 vanilla effects. Explore the category →
Conjugation · 3rd grade
Conjugate finir in the present tense with the pronoun on the front face.
Your answer:
Turn the die with the mouse, a finger or the arrow keys.
Move #2027-118 · truck 2
Stonemasonry workshop · glossary
Bed: the face set on the mortar.Upper bed: takes the stone above.Face: the one you see on the wall.
The .fx-0001-root root is 250 px tall, rgb(26, 26, 36) background. It centers .cube-container, a 100 px square that is both the camera (perspective: 600px) and the area that listens to the pointer. Inside it, .cube keeps its six faces in 3D (transform-style: preserve-3d) and rests at rotateX(-20deg) rotateY(-30deg): at three-quarters, you see the front, the right side and the top. Each 100 px .cube-face is pushed 50 px in its direction (translateZ(50px) after a 90 or 180° rotation) and has its own color at 80%: indigo front, violet back, magenta right, cyan left, green top, pink bottom. Back sides stay visible: through the front faces, you read the far ones mirrored.
The script finds every .fx-0001-root on the page and gives each its own cube. On pointermove and pointerdown (mouse, finger or pen), it measures the pointer's distance from the area's center and turns it into two angles: rotateX(-y / 5) and rotateY(x / 5). The cube therefore turns toward the pointer, one degree every 5 px: ±10° at most in the 100 px area, ±36° if you enlarge the area to 360 px as in the examples. The 0.1 s transition (ease-out) smooths the motion, and the jump on entry: when the pointer arrives in a small area, the cube goes from its three-quarter pose to an angle close to face-on. On pointerleave, it goes back to three-quarters. The area has touch-action: none: on a touch screen, sliding a finger over it turns the cube instead of scrolling the page, and it settles back when the finger lifts.
With the keyboard, Tab reaches the area (tabindex="0", 2 px #a5b4fc outline and brighter edges on focus): the arrow keys turn the cube in 15° steps, with no limit, so every face can be reached; Escape or losing focus puts it back at three-quarters. Measured in Chromium 151 and Firefox 153: pointer 40 px right of and 30 px above the center → rotateX(6deg) rotateY(8deg); right, right, up → rotateX(-5deg) rotateY(0deg); finger slide (Chromium, touch events) → the cube follows, the page stays put; two copies on one page → only the hovered one moves; 0 errors. Playwright's WebKit flattens all CSS 3D: rendering on a real Safari was not verified.
prefers-reduced-motion: reduce, the script stops following the pointer and the CSS removes the transition (a block scoped to .fx-0001-root): the cube stays at three-quarters when hovered. The arrow keys still turn it, on request and in steps, with no animation. Measured in Chromium and Firefox: the cube keeps its pose when the pointer passes over it, and 0% of pixels change over 0.8 s.aria-label) mentions the arrow keys: rewrite it in your page's language, as in the examples.touch-action: none on a 100 px area does not stop the page from scrolling elsewhere. If you make the area much larger, switch it to touch-action: pan-y (as in the examples): vertical scrolling stays possible and a horizontal slide turns the cube.CSS (3D transform, preserve-3d, perspective, touch-action) + 1.8 KB of JavaScript (pointer events, keydown, matchMedia), no dependencies. Measured in Chromium 151 and Firefox 153: same cube (0.57% difference on the still frame), orientation with the mouse and keyboard, two independent copies, 0 errors; finger slide measured in Chromium. Playwright's WebKit 26.5 flattens all CSS 3D: the real Safari was not verified.
Without JavaScript, the cube stays still at its three-quarter pose, three faces visible. Without preserve-3d, the six faces stack flat and only the last one (the pink bottom) stays readable.
Copy the three blocks into your page. No dependencies.
<div class="fx-0001-root">
<div class="demo-3d">
<div class="cube-container" tabindex="0" role="group" aria-label="3D cube: point at it, or use the arrow keys">
<div class="cube">
<div class="cube-face front">Front</div>
<div class="cube-face back">Back</div>
<div class="cube-face right">Right</div>
<div class="cube-face left">Left</div>
<div class="cube-face top">Top</div>
<div class="cube-face bottom">Bottom</div>
</div>
</div>
</div>
</div>
.fx-0001-root,
.fx-0001-root *,
.fx-0001-root *::before,
.fx-0001-root *::after {
box-sizing: border-box
}
.fx-0001-root {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 250px;
overflow: hidden;
position: relative;
background: rgb(26, 26, 36);
color: rgb(255, 255, 255);
font-family: sans-serif;
}
.demo-3d {
width: 280px;
height: 200px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.cube-container {
width: 100px;
height: 100px;
perspective: 600px;
/* A finger turns the cube instead of scrolling the page (100 px area). */
touch-action: none;
outline: none;
}
.cube-container:focus-visible {
outline: 2px solid #a5b4fc;
outline-offset: 22px;
border-radius: 6px;
}
.cube-container:focus-visible .cube-face {
border-color: rgba(255, 255, 255, 0.9);
}
.cube {
width: 100%;
height: 100%;
position: relative;
transform-style: preserve-3d;
transform: rotateX(-20deg) rotateY(-30deg);
transition: transform 0.1s ease-out;
}
.cube-face {
position: absolute;
width: 100px;
height: 100px;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
font-size: 14px;
border: 2px solid rgba(255, 255, 255, 0.3);
backface-visibility: visible;
}
.cube-face.front {
background: rgba(99, 102, 241, 0.8);
transform: translateZ(50px);
}
.cube-face.back {
background: rgba(139, 92, 246, 0.8);
transform: rotateY(180deg) translateZ(50px);
}
.cube-face.right {
background: rgba(217, 70, 239, 0.8);
transform: rotateY(90deg) translateZ(50px);
}
.cube-face.left {
background: rgba(6, 182, 212, 0.8);
transform: rotateY(-90deg) translateZ(50px);
}
.cube-face.top {
background: rgba(16, 185, 129, 0.8);
transform: rotateX(90deg) translateZ(50px);
}
.cube-face.bottom {
background: rgba(244, 63, 94, 0.8);
transform: rotateX(-90deg) translateZ(50px);
}
/* Reduced motion: the cube no longer follows the pointer and stays at its three-quarter pose;
the arrow keys still turn it, in 15° steps, with no transition. */
@media (prefers-reduced-motion: reduce) {
.fx-0001-root .cube { transition: none }
}
(function() {
// Rotating Cube: the cube turns toward the pointer (mouse or finger) and goes back to its three-quarter pose when it leaves.
// With the keyboard (Tab), the arrow keys turn it in 15° steps; Escape puts it back at three-quarters.
// One cube per .fx-0001-root: several copies can live on the same page.
var reduce = window.matchMedia('(prefers-reduced-motion: reduce)');
var REST_X = -20, REST_Y = -30;
document.querySelectorAll('.fx-0001-root').forEach(function(root) {
var cube = root.querySelector('.cube');
var zone = root.querySelector('.cube-container');
if (!cube || !zone) return;
var keyX = REST_X, keyY = REST_Y;
function turn(x, y) {
cube.style.transform = 'rotateX(' + x + 'deg) rotateY(' + y + 'deg)';
}
function rest() {
keyX = REST_X;
keyY = REST_Y;
turn(REST_X, REST_Y);
}
function follow(e) {
if (reduce.matches) return; // reduced motion: no tilt following the pointer
var rect = zone.getBoundingClientRect();
var x = e.clientX - rect.left - rect.width / 2;
var y = e.clientY - rect.top - rect.height / 2;
turn(-y / 5, x / 5);
}
zone.addEventListener('pointermove', follow);
zone.addEventListener('pointerdown', follow);
zone.addEventListener('pointerleave', rest);
zone.addEventListener('keydown', function(e) {
if (e.key === 'Escape') { rest(); return; }
var step = { ArrowUp: [15, 0], ArrowDown: [-15, 0], ArrowLeft: [0, -15], ArrowRight: [0, 15] }[e.key];
if (!step) return;
e.preventDefault(); // the arrow keys turn the cube, they do not scroll the page
keyX += step[0];
keyY += step[1];
turn(keyX, keyY);
});
zone.addEventListener('blur', rest);
});
})();
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Listening area size (CSS — width / height of .cube-container) |
100 px, the cube's size | The tilt equals the distance from the center divided by 5: a 100 px area gives ±10°, a 300 px area ±30°. To enlarge the area without enlarging the cube, center .cube in it (display: flex, and a fixed size for .cube), as in the examples. |
Sensitivity (JS — -y / 5 and x / 5 in follow) |
1° every 5 px | / 3 makes the cube livelier (±17° in 100 px); / 8 calmer. To cap the angle, wrap it in Math.max(-30, Math.min(30, …)). |
Rest pose (JS — REST_X, REST_Y; CSS — transform of .cube) |
-20°, -30° | Change both together: the CSS sets the pose before the script runs, the script sets the pose it returns to. -35 / 45 shows more of the top; 0 / 0 presents the front face flat. |
Keyboard step (JS — the 15 values in the step table) |
15° per press | 90 moves from one face to the next on each press, handy for a die meant to be read face by face. |
Cube size (CSS — 100px on the faces, translateZ(50px)) |
100 px | The push is half the side: 120 px side, translateZ(60px) in all six face rules. |
Faces (HTML and CSS — text and background of each .cube-face) |
six colors at 80%, labels Front to Bottom | Below 0.6 opacity, the opposite face reads clearly through; at 1, the cube turns solid and the hidden faces disappear. |
Because the area that listens to the pointer is only 100 px, the size of the cube: at 1° every 5 px, the tilt never exceeds 10°. Enlarge .cube-container (and center the cube in it) for a wider motion, as in the three examples, or divide by a smaller number in the script.
Yes. The script goes through every .fx-0001-root on the page and gives each its own area, cube and keyboard state; it relies on no id. Measured with two copies: only the hovered one moves.
Cube Auto-Rotation turns on its own, endlessly, with six faces of the same color: an object in midair. Rotating Cube only moves when you orient it, with faces of different colors and names: an object you handle to read each side.