<h1>CSS Transform</h1>
<div class="controls"><button class="reset">Toggle transformations</button></div>
<div class="container">
	<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/9729/dad01.png" id="no1" />
</div>
<svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <path id="_scale" d="M57.912,75l17.088,0l0,-17.088m-50,-15.824l0,-17.088l17.088,0" style="fill:none;stroke:white;stroke-width:2px;"/>
    <path id="_perspective" d="M25,65.492l15.135,-29.411l19.73,0l15.135,29.411l-50,0Z" style="fill:none;stroke:white;stroke-width:2px;"/>
    <g id="_rotate">
        <path d="M68.752,50c0,10.349 -8.403,18.752 -18.752,18.752c-10.349,0 -18.752,-8.403 -18.752,-18.752c0,-10.349 8.403,-18.752 18.752,-18.752" style="fill:none;stroke:white;stroke-width:2px;stroke-linecap:butt;"/>
        <path d="M55.505,31.248l-5.43,4.833l0,-9.666l5.43,4.833Z" style="fill:white;"/>
    </g>
    <g id="_skewX">
        <path d="M59.376,54.009c0,0 -8.402,0 -18.752,0" style="fill:none;stroke:white;stroke-width:2px;stroke-linecap:butt;"/>
        <path d="M35.119,54.009l5.43,-4.833l0,9.666l-5.43,-4.833Z" style="fill:white;"/>
        <path d="M40.624,45.991c0,0 8.402,0 18.752,0" style="fill:none;stroke:white;stroke-width:2px;stroke-linecap:butt;"/>
        <path d="M64.881,45.991l-5.43,4.833l0,-9.666l5.43,4.833Z" style="fill:white;"/>
    </g>
    <g id="_skewY">
        <path d="M45.991,59.376c0,0 0,-8.402 0,-18.752" style="fill:none;stroke:white;stroke-width:2px;stroke-linecap:butt;"/>
        <path d="M45.991,35.119l4.833,5.43l-9.666,0l4.833,-5.43Z" style="fill:white;"/>
        <path d="M54.009,40.624c0,0 0,8.402 0,18.752" style="fill:none;stroke:white;stroke-width:2px;stroke-linecap:butt;"/>
        <path d="M54.009,64.881l-4.833,-5.43l9.666,0l-4.833,5.43Z" style="fill:white;"/>
    </g>
    <g id="_translateY">
        <path d="M49.991,59.376c0,0 0,-8.402 0,-18.752" style="fill:none;stroke:white;stroke-width:2px;stroke-linecap:butt;"/>
        <path d="M49.991,36.119l4.833,5.43l-9.666,0l4.833,-5.43Z" style="fill:white;"/>
        <path d="M50.009,63.881l-4.833,-5.43l9.666,0l-4.833,5.43Z" style="fill:white;"/>
    </g>
    <g id="_rotateY">
        <path d="M61.309,56.755c-8.377,2.704 -20.112,1.873 -26.189,-1.856c-6.076,-3.728 -4.207,-8.95 4.171,-11.654c8.377,-2.704 20.112,-1.873 26.189,1.856" style="fill:none;stroke:white;stroke-width:2px;stroke-linecap:butt;"/>
        <path d="M50,70.007l0.603,-40.014" style="fill:none;stroke:white;stroke-width:2px;stroke-linecap:butt;"/>
        <path d="M67.725,46.583l-7.1,-0.694l7.825,-2.525l-0.725,3.219Z" style="fill:white;"/>
    </g>
    <g id="_rotateX">
        <path d="M42.322,60.407c-1.973,-8.58 -0.133,-20.199 4.105,-25.932c4.238,-5.732 9.279,-3.421 11.252,5.159c1.972,8.579 0.132,20.199 -4.106,25.932" style="fill:none;stroke:white;stroke-width:2px;stroke-linecap:butt;"/>
        <path d="M70.007,50.323l-40.014,-0.603" style="fill:none;stroke:white;stroke-width:2px;stroke-linecap:butt;"/>
        <path d="M51.903,67.675l1.303,-7.014l1.842,8.013l-3.145,-0.999Z" style="fill:white;"/>
    </g>
    <g id="_rotateZ">
        <path d="M45.325,57.257c-1.406,-6.116 -0.161,-14.311 2.778,-18.287c2.94,-3.976 6.468,-2.238 7.874,3.879c1.406,6.117 0.161,14.311 -2.778,18.287" style="fill:none;stroke:white;stroke-width:2px;stroke-linecap:butt;"/>
        <path d="M62.878,40.62l-25.756,18.518" style="fill:none;stroke:white;stroke-width:2px;stroke-linecap:butt;"/>
        <path d="M51.739,62.431l0.828,-4.904l1.358,5.638l-2.186,-0.734Z" style="fill:white;"/>
    </g>
    <g id="_translateX">
        <path d="M40.624,49.991c0,0 8.402,0 18.752,0" style="fill:none;stroke:white;stroke-width:2px;stroke-linecap:butt;"/>
        <path d="M63.881,49.991l-5.43,4.833l0,-9.666l5.43,4.833Z" style="fill:white;"/>
        <path d="M36.119,50.009l5.43,-4.833l0,9.666l-5.43,-4.833Z" style="fill:white;"/>
    </g>
</svg>
<div class="style"></div>
@import url(https://fonts.googleapis.com/css?family=Inconsolata:400,700|Open+Sans:400,800);

:root {
	--fast-animation: .4s;
}

html, body {
font-family: 'Open Sans', sans-serif;
	background: black;
	margin: 0;
	padding: 0;
	overflow: hidden;
	width: 100%;
	height: 100%;
}
* {
	box-sizing: border-box;
	transform-style: preserve-3d;
}
button {
	clear: both;
	width: 64%;
	margin-bottom: 5px;
	font-size: 20px;
	border-radius: 3px;
	color: black;
	background: #eee;
}
button:active {
	box-shadow: none;
	outline: none;
}
h1, h2 {
	color: white;
	font-weight: 300;
	position: absolute;
	left: .5em;
	z-index:10;
	text-shadow:  2px 2px 0px rgba(220,220,220,0.5), 2px 2px 0px rgba(0,0,0,0.5);
}
h2 {
	top: 0;
	margin: 250px 0 0 350px;;
}
#no1 {
	perspective: 250px;
	transform: skewX(120deg);
	transition: all 2.5s;
	z-index: 1;
	position: absolute;
	left: 25vw;
	top: 25vh;
}
.container, .container * {
	z-index: 1;
}
.controls {
	position: absolute;
	z-index: 1110;
	height: 10vh;
	top: 0;
	right: 0;
	width: 430px;
	padding-top: 20px;
}


.pair {
	display: flex;
	color: white;
}

.pair label {
	margin-top: 10px;
}


/* https://css-tricks.com/styling-cross-browser-compatible-range-inputs-css/ */
input {
	height: 40px;
}
input[type=range] {
  -webkit-appearance: none; /* Hides the slider so that custom slider can be made */
  width: 64%; /* Specific width is required for Firefox. */
  background: transparent; /* Otherwise white in Chrome */
}

input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none;
}

input[type=range]:focus {
  outline: none; /* Removes the blue border. You should probably do some kind of focus styling for accessibility reasons though. */
}

input[type=range]::-ms-track {
  width: 100%;
  cursor: pointer;

  /* Hides the slider so custom styles can be added */
  background: transparent; 
  border-color: transparent;
  color: transparent;
}

/* Special styling for WebKit/Blink */
input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none;
  border: 1px solid #000000;
  height: 36px;
  width: 16px;
  border-radius: 3px;
  background: #ffffff;
  cursor: pointer;
  margin-top: -14px; /* You need to specify a margin in Chrome, but in Firefox and IE it is automatic */
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; /* Add cool effects to your sliders! */
}

/* All the same stuff for Firefox */
input[type=range]::-moz-range-thumb {
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
  border: 1px solid #000000;
  height: 36px;
  width: 16px;
  border-radius: 3px;
  background: #ffffff;
  cursor: pointer;
}

/* All the same stuff for IE */
input[type=range]::-ms-thumb {
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
  border: 1px solid #000000;
  height: 36px;
  width: 16px;
  border-radius: 3px;
  background: #ffffff;
  cursor: pointer;
}

input[type=range]::-webkit-slider-runnable-track {
  width: 70%;
  height: 8.4px;
  cursor: pointer;
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
  background: #aaa;
  border-radius: 1.3px;
  border: 0.2px solid #010101;
}

input[type=range]:focus::-webkit-slider-runnable-track {
  background: #367ebd;
}

input[type=range]::-moz-range-track {
  width: 70%;
  height: 8.4px;
  cursor: pointer;
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
  background: #aaa;
  border-radius: 1.3px;
  border: 0.2px solid #010101;
}

input[type=range]::-ms-track {
  width: 70%;
  height: 8.4px;
  cursor: pointer;
  background: transparent;
  border-color: transparent;
  border-width: 16px 0;
  color: transparent;
}
input[type=range]::-ms-fill-lower {
  background: #2a6495;
  border: 0.2px solid #010101;
  border-radius: 2.6px;
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
}
input[type=range]:focus::-ms-fill-lower {
  background: #aaa;
}
input[type=range]::-ms-fill-upper {
  background: #aaa;
  border: 0.2px solid #010101;
  border-radius: 2.6px;
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
}
input[type=range]:focus::-ms-fill-upper {
  background: #367ebd;
}
#_rotate {
	transform-origin: 50% 50%;
}
svg path {
	display: none;
	transition: all .4s;
}
.scale #_scale,
.perspective #_perspective,
.rotate #_rotate *,
.rotateY #_rotateY *,
.rotateX #_rotateX *,
.rotateZ #_rotateZ *,
.skewX #_skewX *,
.skewY #_skewY *,
.translateY #_translateY *,
.translateX #_translateX *{
	display: block;
	transition: all .4s;
}

.fast #no1 {
	transition: all var(--fast-animation);
}

.style {
	position: fixed;
	bottom: 10px;
	left: 10px;
	color: hsla(0,0%,90%,.74);
	font-family: monospace;
	user-select: all;
}
var propObject = {};
const body = document.body;
const style = document.querySelector(".style");
var values = [
	{
		parentprop: "",
		prop: "perspective",
		default: "1000",
		template: "%value%px",
		min: "10",
		max: "10000",
		step: "1",
		target: ".container"
	},
	{
		parentprop: "transform",
		prop: "rotate",
		default: "0",
		template: "%prop%(%value%deg)",
		min: 0,
		max: 360,
		step: 1
	},
	{
		parentprop: "transform",
		prop: "rotateX",
		default: "0",
		template: "%prop%(%value%deg)",
		min: 0,
		max: 360,
		step: 1
	},
	{
		parentprop: "transform",
		prop: "rotateY",
		default: "0",
		template: "%prop%(%value%deg)",
		min: 0,
		max: 360,
		step: 1
	},
	{
		parentprop: "transform",
		prop: "rotateZ",
		default: "0",
		template: "%prop%(%value%deg)",
		min: 0,
		max: 360,
		step: 1
	},
	{
		parentprop: "transform",
		prop: "scale",
		default: "1",
		template: "%prop%(%value%)",
		min: "0",
		max: "6",
		step: ".05"
	},
	{
		parentprop: "transform",
		prop: "skewX",
		default: "0",
		template: "%prop%(%value%deg)",
		min: -360,
		max: 360,
		step: 1
	},
	{
		parentprop: "transform",
		prop: "skewY",
		default: "0",
		template: "%prop%(%value%deg)",
		min: -360,
		max: 360,
		step: 1
	},
	{
		parentprop: "transform",
		prop: "translateX",
		default: "0",
		template: "%prop%(%value%px)",
		min: -1500,
		max: 1500,
		step: 1
	},
	{
		parentprop: "transform",
		prop: "translateY",
		default: "0",
		template: "%prop%(%value%px)",
		min: -1500,
		max: 1500,
		step: 1
	}
];

var controls = document.querySelector(".controls"),
	target = document.querySelector("#no1"),
	btnReset = document.querySelector(".reset"),
	toggle = true;

btnReset.onclick = reset;
/*
{
	prop:
	{
		parentProp,
		value,
		target
	}
}
*/
var targetProps = {};

values.forEach(function (controle) {
	addControl(controle);
});

function addControl(controle) {
	var ele = getElement("input", {
		type: "range",
		value: controle.default,
		min: controle.min,
		max: controle.max,
		step: controle.step,
		class: "control " + controle.prop,
		prop: controle.prop,
		target: controle.target || "#no1",
		parentprop: controle.parentprop,
		default: parseTemplate(controle.template, controle.prop, controle.default),
		template: controle.template
	});
	var lbl = getElement("label", {});
	ele.oninput = ele.onclick = propChanged;
	var div = getElement("div", { class: "pair" });

	div.appendChild(ele);
	div.appendChild(lbl);
	controls.appendChild(div);
	propChanged(ele);
}

let currentProp, hideTimer;
function showAxis(prop) {
	if (currentProp !== null) body.classList.remove(currentProp);
	currentProp = prop;
	body.classList.add(currentProp);
	body.classList.add("fast");
	if (hideTimer) {
		clearTimeout(hideTimer);
	}
	if (propObject[prop]) {
		switch (prop) {
			case "rotate":
				propObject["rotate"].style.transform = targetProps[prop].value;
				break;
		}
	}
	hideTimer = setTimeout(() => {
		body.classList.remove(currentProp);
		body.classList.remove("fast");
		currentProp = null;
	}, 1000);
}

function propChanged(e) {
	var targ = e.target ? e.target : e,
		prop = targ.getAttribute("prop"),
		defValue = targ.getAttribute("default"),
		parentProp = targ.getAttribute("parentprop"),
		template = targ.getAttribute("template"),
		propTarget = targ.getAttribute("target"),
		lbl = document.querySelector("." + prop + " + label");
	showAxis(prop);
	var attValue = parseTemplate(template, prop, targ.value);
	lbl.innerText = prop + " " + targ.value;

	targetProps[prop] = {
		parentProp: parentProp,
		value: attValue,
		target: propTarget ? propTarget : "#no1",
		defValue: defValue
	};
	updateProperties(target);
}

function reset() {
	updateProperties(target, toggle);
	toggle = !toggle;
}

function updateProperties(ele, bDefault) {
	var props = {};
	const keys = Object.keys(targetProps);
	keys.forEach((key) => {
		var obj = targetProps[key],
			parentProp = obj.parentProp || key;
		var val = bDefault ? obj.defValue : obj.value;
		if (typeof props[parentProp] === "undefined") {
			props[parentProp] = { value: val, target: obj.target };
		} else {
			props[parentProp].value += " " + val;
		}
	});
	let styles = "";
	const keys = Object.keys(props);
	keys.forEach((key) => {
		var propTarget = document.querySelector(props[key].target);
		propTarget.style[key] = props[key].value;
		styles += (styles === "" ? "" : "; ") + key + ": " + props[key].value;
	});
	style.innerText = styles;
}

function parseTemplate(temp, prop, value) {
	var res = temp.replace(/%prop%/gi, prop),
		res = res.replace(/%value%/gi, value);
	return res;
}

function getElement(tagName, attributes) {
	var ele = document.createElement(tagName);
	if (attributes) {
		const keys = Object.keys(attributes);
		keys.forEach((key) => {
			ele.setAttribute(key, attributes[key]);
		});
	}

	return ele;
}

values.forEach((controle) => {
	propObject[controle.prop] = document.getElementById("_" + controle.prop);
});
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.