<div class="outer">
<input type="checkbox" id="usePerspective" class="hidden" onchange="setActive(this);" checked>
<input type="checkbox" id="runAnimation" class="hidden" onchange="setAnimation(this);">
<div class="labels">
<label for="usePerspective" class="usePerspective">
Use perspective
</label>
<label for="runAnimation" class="runAnimation">
Run animation
</label>
</div>
<div class="slider1">
<input type="range" class="vertical" data-var="prespective" data-unit="px" min="250" max="2500" value="1000" oninput="setCssVariables(this);">
</div>
<div class="container">
<div class="cube">
<div class="side front"></div>
<div class="side left"></div>
<div class="side right"></div>
<div class="side back"></div>
<div class="side top"></div>
<div class="side bottom"></div>
</div>
</div>
<div class="slider2">
<input type="range" class="vertical" data-var="originVertical" data-unit="%" min="-100" max="200" value="0" oninput="setCssVariables(this);">
</div>
<div class="slider3">
<input type="range" class="horizontal" data-var="originHorizontal" data-unit="%" min="-100" max="200" value="100" oninput="setCssVariables(this);">
</div>
</div>
:root {
--prespective: 1000px;
--originVertical: 0%;
--originHorizontal: 100%;
}
*, *::before, *::after {
padding: 0;
margin: 0 auto;
box-sizing: border-box;
}
body {
font-family: 'Anton', sans-serif;
background-color: #eee;
color: #333;
min-height: 100vh;
display: -webkit-box;
display: flex;
-webkit-box-pack: center;
justify-content: center;
-webkit-box-align: center;
align-items: center;
overflow: hidden;
}
.outer {
display: grid;
grid-template-columns: 2em 400px 2em;
grid-gap: 1em;
}
.container {
width: 400px;
height: 400px;
border: 2px solid white;
border-radius: 4px;
display: -webkit-box;
display: flex;
-webkit-box-pack: center;
justify-content: center;
-webkit-box-align: center;
align-items: center;
pointer-events: none;
-webkit-perspective: var(--prespective);
perspective: var(--prespective);
-webkit-perspective-origin: var(--originHorizontal) var(--originVertical);
perspective-origin: var(--originHorizontal) var(--originVertical);
}
.cube {
position: relative;
width: 200px;
height: 200px;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
.cube.animated {
-webkit-animation: cubeRotate 10s linear infinite;
animation: cubeRotate 10s linear infinite;
}
@-webkit-keyframes cubeRotate {
from {
-webkit-transform: rotateY(0deg) rotateX(720deg) rotateZ(0deg);
transform: rotateY(0deg) rotateX(720deg) rotateZ(0deg);
}
to {
-webkit-transform: rotateY(360deg) rotateX(0deg) rotateZ(360deg);
transform: rotateY(360deg) rotateX(0deg) rotateZ(360deg);
}
}
@keyframes cubeRotate {
from {
-webkit-transform: rotateY(0deg) rotateX(720deg) rotateZ(0deg);
transform: rotateY(0deg) rotateX(720deg) rotateZ(0deg);
}
to {
-webkit-transform: rotateY(360deg) rotateX(0deg) rotateZ(360deg);
transform: rotateY(360deg) rotateX(0deg) rotateZ(360deg);
}
}
.side {
position: absolute;
width: 100%;
height: 100%;
opacity: 0.75;
border: 2px solid white;
}
.front {
background-color: #D50000;
-webkit-transform: translateZ(100px);
transform: translateZ(100px);
}
.back {
background-color: #AA00FF;
-webkit-transform: translateZ(-100px);
transform: translateZ(-100px);
}
.left {
background-color: #304FFE;
-webkit-transform: rotateY(90deg) translateZ(100px);
transform: rotateY(90deg) translateZ(100px);
}
.right {
background-color: #0091EA;
-webkit-transform: rotateY(-90deg) translateZ(100px);
transform: rotateY(-90deg) translateZ(100px);
}
.top {
background-color: #00BFA5;
-webkit-transform: rotateX(90deg) translateZ(100px);
transform: rotateX(90deg) translateZ(100px);
}
.bottom {
background-color: #64DD17;
-webkit-transform: rotateX(-90deg) translateZ(100px);
transform: rotateX(-90deg) translateZ(100px);
}
.vertical {
width: 2em;
height: 400px;
-webkit-appearance: slider-vertical;
}
.horizontal {
width: 400px;
}
.hidden {
position: fixed;
top: -10000px;
left: -10000px;
visibility: hidden;
}
.labels {
grid-column: 1 / -1;
}
label.usePerspective, label.runAnimation {
text-align: center;
padding: 0.5em 1em;
border: 1px solid #777;
border-radius: 4px;
margin-top: 1.5em;
}
label.usePerspective + label, label.runAnimation + label {
margin-left: 1em;
}
.slider1 {
position: relative;
}
.slider1::after {
content: "Perspective value";
width: 400px;
text-align: center;
position: absolute;
left: 0;
bottom: 50%;
font-size: 1em;
opacity: 0.25;
-webkit-transform: translateX(-50%) rotate(-90deg);
transform: translateX(-50%) rotate(-90deg);
-webkit-transform-origin: bottom;
transform-origin: bottom;
}
.slider2 {
position: relative;
}
.slider2::after {
content: "Perspective origin - Vertical";
width: 400px;
text-align: center;
position: absolute;
right: 0;
bottom: 50%;
font-size: 1em;
opacity: 0.25;
-webkit-transform: translateX(50%) rotate(90deg);
transform: translateX(50%) rotate(90deg);
-webkit-transform-origin: bottom;
transform-origin: bottom;
}
.slider3 {
grid-column: 2 / 3;
position: relative;
}
.slider3::after {
content: "Perspective origin - Horizontal";
width: 400px;
text-align: center;
position: absolute;
right: 0;
top: 100%;
opacity: 0.25;
font-size: 1em;
-webkit-transform-origin: bottom;
transform-origin: bottom;
}
#usePerspective:checked ~ div label.usePerspective {
background-color: greenyellow;
}
#usePerspective:checked ~ *::after {
opacity: 1;
}
#runAnimation:checked ~ div label.runAnimation {
background-color: greenyellow;
}
function setCssVariables(obj) {
document.documentElement.style.setProperty(`--${obj.dataset.var}`, obj.value + obj.dataset.unit);
}
function setActive(obj) {
document.querySelectorAll('input[type="range"]').forEach(e => {
e.disabled = !obj.checked
});
document.documentElement.style.setProperty('--prespective', obj.checked ? (document.querySelector('.slider1 > input').value + 'px') : 'none');
}
function setAnimation(obj) {
if (obj.checked) {
document.querySelector('.cube').classList.add('animated')
} else {
document.querySelector('.cube').classList.remove('animated')
}
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.