<div class="case">
<!-- 1 row -->
<div class="key" data-key="prtSc"></div>
<div class="key" data-key="scrLk"></div>
<div class="key" data-key="break"></div>
<!-- 2 row -->
<div class="key" data-key="ins"></div>
<div class="key" data-key="home"></div>
<div class="key" data-key="pgUp"></div>
<!-- 3 row -->
<div class="key" data-key="del"></div>
<div class="key" data-key="end"></div>
<div class="key" data-key="pgDn"></div>
<!-- 4 row -->
<div class="gap"></div>
<div class="gap"></div>
<div class="gap"></div>
<div class="gap"></div>
<div class="gap"></div>
<div class="gap"></div>
<div class="gap"></div>
<!-- 5 row -->
<div class="gap"></div>
<div class="key" data-key="arrowUp">▲</div>
<div class="gap"></div>
<!-- 6 row -->
<div class="key" data-key="arrowLeft">◀</div>
<div class="key" data-key="arrowDown">▼</div>
<div class="key" data-key="arrowRight">▶</div>
</div>
body {
background-color: #625499;
display: table-cell;
height: 100vh;
margin: 0;
text-align: center;
vertical-align: middle;
width: 100vw;
}
.case {
background-color: #463973;
border-color: #2e2640;
border-radius: 5px;
border-style: solid;
border-width: 8px 10px 15px 10px;
display: inline-grid;
grid-template-columns: repeat(6, 1fr);
grid-template-rows: repeat(6, 1fr);
height: 20em;
padding: 5px;
user-select: none;
width: 10em;
}
.key {
border-color: #382e59 #2e2640;
border-radius: 2px;
border-style: solid;
border-width: 3px 5px 8px 5px;
color: #bbadd9;
display: block;
font-family: sans-serif;
font-size: 7px;
font-weight: 800;
grid-column-end: span 2;
margin: 3px;
padding-top: 2px;
padding: 5px;
text-align: center;
text-transform: uppercase;
transition: all 50ms ease-out;
will-change: box-shadow, color, text-shadow;
}
.key:empty::before {
content: attr(data-key);
}
.active {
transform: perspective(1200px) translateZ(-90px);
}
.medium {
grid-column-end: span 3;
}
.large {
grid-column-end: span 4;
}
.xl {
grid-column-end: span 5;
}
.xxl {
grid-column-end: span 6;
}
.xxxl {
grid-column-end: 7;
}
.huge {
grid-column-end: span 12;
}
const keysArr = [...document.querySelectorAll(".key")];
const getKey = (event) => {
const parsedKey = event.key.toLowerCase().replace("\\", "\\\\");
const parsedCode = event.code.toLowerCase();
const element =
document.querySelector(`[data-key="${parsedCode}"]`) ||
document.querySelector(`[data-key="${parsedKey}"]`);
return element;
};
document.addEventListener("keydown", (event) => {
const key = getKey(event);
if (key) {
key.classList.add("active");
}
});
document.addEventListener("keyup", (event) => {
const key = getKey(event);
if (key) {
key.classList.remove("active");
}
});
document.addEventListener("mousedown", (event) => {
if (event.target.dataset.key) {
event.target.classList.add("active");
}
});
document.addEventListener("mouseup", (event) => {
if (event.target.dataset.key) {
event.target.classList.remove("active");
}
});
document.addEventListener("touchstart", (event) => {
if (event.target.dataset.key) {
event.target.classList.add("active");
}
});
document.addEventListener("touchend", (event) => {
if (event.target.dataset.key) {
event.target.classList.remove("active");
}
});
const animate = (element) => {
const hueColor = Math.floor(Math.random() * (360 - 0 + 1)) + 0;
const color = `hsla(${hueColor}, 100%, 50%, 50%)`;
const textColor = `hsl(${hueColor}, 100%, 50%)`;
const textShadow = `0 0 0.80em ${color}, 0 0 1.60em ${color}, 0 0 4em ${color}`;
const boxShadow = `-3px 3px 4px ${color}, 3px -3px 4px ${color}, 3px 3px 4px ${color}, -3px -3px 4px ${color}, 0 0 10px ${color}`;
const keyIndex = keysArr.indexOf(element);
const animatedKeysRight = keysArr.slice(keyIndex);
const animatedKeysLeft = keysArr.slice(0, keyIndex);
const transitionHandler = (event) => {
event.target.style.boxShadow = "none";
event.target.style.color = null;
event.target.style.textShadow = "none";
event.target.removeEventListener("transitionend", transitionHandler);
};
animatedKeysRight.forEach((keyEl, i) => {
setTimeout(() => {
keyEl.addEventListener("transitionend", transitionHandler);
keyEl.style.boxShadow = boxShadow;
keyEl.style.color = textColor;
keyEl.style.textShadow = textShadow;
}, i * 35);
});
animatedKeysLeft.forEach((keyEl, j) => {
const i = animatedKeysLeft.length - j;
setTimeout(() => {
keyEl.addEventListener("transitionend", transitionHandler);
keyEl.style.boxShadow = boxShadow;
keyEl.style.color = textColor;
keyEl.style.textShadow = textShadow;
}, i * 35);
});
};
document.addEventListener("keydown", (event) => {
const key = getKey(event);
if (key) {
animate(key);
}
});
document.addEventListener("click", (event) => {
if (event.target.dataset.key) {
animate(event.target);
}
});
window.addEventListener("load", () => {
const key = document.querySelector(`[data-key="enter"]`);
animate(key);
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.