<!--There are probably better ways to do this than hard-code everything in the HTML, but ¯\_(ツ)_/¯ -->
<div id="text">
	<div id="enteredText">Click here, then start typing!</div>
<div class="container">
	<div id="keyboard">
		<div id="firstrow" class="keyboard-row">
			<kbd class="shifter" id="192">`</kbd>
			<kbd class="shifter" id="49">1</kbd>
			<kbd class="shifter" id="50">2</kbd>
			<kbd class="shifter" id="51">3</kbd>
			<kbd class="shifter" id="52">4</kbd>
			<kbd class="shifter" id="53">5</kbd>
			<kbd class="shifter" id="54">6</kbd>
			<kbd class="shifter" id="55">7</kbd>
			<kbd class="shifter" id="56">8</kbd>
			<kbd class="shifter" id="57">9</kbd>
			<kbd class="shifter" id="48">0</kbd>
			<kbd class="shifter" id="189">-</kbd>
			<kbd class="shifter" id="187">=</kbd>
			<kbd class="long operationKey" id="8">del</kbd>
		<div id="secondrow" class="keyboard-row">
			<kbd class="long operationKey" id="9">tab</kbd>
			<kbd id="81">q</kbd>
			<kbd id="87">w</kbd>
			<kbd id="69">e</kbd>
			<kbd id="82">r</kbd>
			<kbd id="84">t</kbd>
			<kbd id="89">y</kbd>
			<kbd id="85">u</kbd>
			<kbd id="73">i</kbd>
			<kbd id="79">o</kbd>
			<kbd id="80">p</kbd>
			<kbd class="shifter" id="219">[</kbd>
			<kbd class="shifter" id="221">]</kbd>
			<kbd class="shifter" id="220">\</kbd>
		<div id="thirdrow" class="keyboard-row">
			<kbd class="long operationKey" id="20">caps</kbd>
			<kbd id="65">a</kbd>
			<kbd id="83">s</kbd>
			<kbd id="68">d</kbd>
			<kbd id="70">f</kbd>
			<kbd id="71">g</kbd>
			<kbd id="72">h</kbd>
			<kbd id="74">j</kbd>
			<kbd id="75">k</kbd>
			<kbd id="76">l</kbd>
			<kbd class="shifter" id="186">;</kbd>
			<kbd class="shifter" id="222">'</kbd>
			<kbd class="long operationKey" id="13">return</kbd>
		<div id="fourthrow" class="keyboard-row">
			<kbd class="longer operationKey" id="16">shift</kbd>
			<kbd id="90">z</kbd>
			<kbd id="88">x</kbd>
			<kbd id="67">c</kbd>
			<kbd id="86">v</kbd>
			<kbd id="66">b</kbd>
			<kbd id="78">n</kbd>
			<kbd id="77">m</kbd>
			<kbd class="shifter" id="188">,</kbd>
			<kbd class="shifter" id="190">.</kbd>
			<kbd class="shifter" id="191">/</kbd>
			<kbd class="longer operationKey" id="16">shift</kbd>
		<div id="fifthrow" class="keyboard-row">
			<kbd class="operationKey" id="188">fn</kbd>
			<kbd class="operationKey" id="17">ctrl</kbd>
			<kbd class="operationKey" id="18">opt</kbd>
			<kbd class="long operationKey" id="91">⌘</kbd>
			<kbd class="spacebar operationKey" id="32">&nbsp;</kbd>
			<kbd class="long operationKey" id="91">⌘</kbd>
			<kbd class="operationKey" id="18">opt</kbd>
			<kbd class="operationKey" id="17">ctrl</kbd>
			<kbd class="operationKey" id="188">fn</kbd>
<br><pre style="width: 100%; text-align: center;">Click the screen or type shift + delete to clear all text.</pre>
//Set up some color variables
$darkgray: #53565a;
$midgray: #888b8d;
$lightgray: #a7a8aa;
$yellow: #ffd100;

//Lots of stuff be flexin'
@mixin flexy {
	display: -webkit-box;
	display: -ms-flexbox;
	display: flex;
	-webkit-box-pack: center;
	-ms-flex-pack: center;
	        justify-content: center;
	-webkit-box-align: center;
	-ms-flex-align: center;
	        align-items: center;
	-ms-flex-line-pack: center;
	    align-content: center;
	-ms-flex-wrap: wrap;
	    flex-wrap: wrap;

* {
	box-sizing: border-box;

body {
	//Change this font-size value to resize the keyboard!
	font-size: 8px;
	@include flexy;
	width: 100%;
	margin: 0;
	box-sizing: border-box;
	font-family: Quicksand;
	height: 100vh;
	max-height: 100vh;
	overflow: hidden;
	//The keyboard containing div and all key elements
	#keyboard, kbd {
		@include flexy;
		box-sizing: border-box;
		border-radius: 4px;
		background: #ccc;
		border: .2em solid $midgray;
		text-align: center;
		font-family: Quicksand;
	kbd {
		flex: 1;
	.keyboard-row {
		@include flexy;
		width: 100%;
	//The box the typed text appears in
	div#text {
		@include flexy;
		align-items: flex-end;
		width: 20em;
		height: 44vh;
		max-height: 44vh;
		font-size: 3em;
		margin-bottom: 4vh;
		text-align: center;
		overflow: auto;
		align-self: flex-end;
		position: relative;
	//The div containing the keys
	#keyboard {
		width: 56em;
		padding: .4em .4em .8em;
		box-shadow: 0 .4em 0 $midgray;
		//The elements that make up the keys themselves
		kbd {
			line-height: 3.2em;
			height: 3.2em;
			width: 3.2em;
			margin: .25em;
			text-align: center;
			color: #fff;
			background-color: $darkgray;
			transition: background, position, top, box-shadow .1s;
			box-shadow: 0px 2px 0px $midgray;

		//For slightly wider keys
		kbd.long {
			flex-grow: 1;
			flex: 2;

		//For much wider keys
		kbd.longer {
			flex-grow: 2;
			flex: 3;
		//For the widest key
		kbd.spacebar {
			flex-grow: 14;
			flex: 6;
		//Keep the keys that aren't letters, numbers and punctuation from going to uppercase when shift or capslock is pressed
		.operationKey {
			text-transform: none!important;

		//Styles applied to a currently-pressed key
		.pressed {
			background: $yellow;
			position: relative;
			top: 2px;
			box-shadow: none;
	//Applied to the whole keyboard when shift or capslock is pressed
	pre {
		height: 3vh;
		line-height: 3vh;
	.uppercase kbd {
		text-transform: uppercase;

//Make keyboard responsive, kinda
@media (min-width: 768px) {
	body {
		font-size: 10px;

@media (min-width: 960px) {
	body {
		font-size: 12px;

@media (min-width: 1080px) {
	body {
		font-size: 14px;
View Compiled
 * There are probably better ways of doing a lot of this,
 * but I'm just starting to wade into the deep end of
 * of vanilla JavaScript, so ¯\_(ツ)_/¯
 * Inspired by day 1 of Wes Bos's 30 Day JavaScript Challenge
 * https://javascript30.com/
var x = 'x';
let theTextBox = document.getElementById('enteredText'); 
let allTheKeys = document.getElementById('keyboard'); 
let changeKeys = document.getElementsByClassName('shifter'); 
let capsLockKey = document.getElementById('20');
let shiftKey = document.getElementById('16');

//Store all the original values of the non-alphabetical keys
var originalShifterArray = []; 
for (i = 0; i<changeKeys.length; i++){

//Set up an array for the replacement values of the non-alphabetical keys that get subbed in when Shift is pressed
var shifterArray = ['~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '{', '}', '|', ':', '"', '<', '>', '?'];

//Function that clears the text box
function clearText(){
	theTextBox.innerHTML = '<br>';

//Function that detects keypresses and does the appropriate things
function highlightAndType(e){
	var keyPressed = e.keyCode;
	var charPressed = e.key;
	const keys = document.getElementById(keyPressed);
		theTextBox.innerHTML = "Sorry, this pen doesn't work in your browser. :( <br> Try Chrome, Firefox or Opera.";
	//If the user presses CapsLock or Shift, make the alphabetical keys uppercase
	if (charPressed == 'CapsLock' || charPressed == 'Shift') {
	//If the user presses Shift, also replace all non-alphabetical keys with their shifted values
	if (charPressed == 'Shift') {
		for(i = 0; i<changeKeys.length; i++){
			changeKeys[i].innerHTML = shifterArray[i];
	//Make sure the key that was typed was a character
	if (e.key.length <= 1){
			var newText = theTextBox.innerHTML.slice(0, -4);
			theTextBox.innerHTML = newText;
		theTextBox.innerHTML += e.key;
	//If a backspace was typed, delete the last character in the text box. If shift was also held, delete all text.
	} else if (e.key == 'Backspace'){
		} else {
			var newText = theTextBox.innerHTML.slice(0, -1);
			theTextBox.innerHTML = newText;
	//If the Enter key was typed, remove all text from the text box
	} else if (e.key == 'Enter'){
		theTextBox.innerHTML += '<br><br>';
	//if Tab is pressed, don't tab out of the window. Add extra space to the text box instead
	if(keyPressed == 9){
		theTextBox.innerHTML += '&emsp;&emsp;';

//Function that detects when the user lets off a key and does the appropriate things
function removeKeypress(e){
	var keyDepressed = e.keyCode;	
	const keys = document.getElementById(keyDepressed);
	//If CapsLock or Shift was just let off, and if the other isn't still on, return keys to lowercase
	if(keyDepressed == 20 && !shiftKey.classList.contains('pressed') || keyDepressed == 16 && !capsLockKey.classList.contains('pressed')) {
	//If Shift was just let off, replace all non-alphabetical keys with their original values rather than their shifted values
	if(keyDepressed == 16 ) {
		for(i = 0; i<changeKeys.length; i++){
			changeKeys[i].innerHTML = originalShifterArray[i];

//Whenever the user presses a key down, run the proper function
window.addEventListener('keydown', highlightAndType );

//Whenever the user lets a key up, run the proper function
window.addEventListener('keyup', removeKeypress );

//Whenever the window is clicked, run the function to clear out the text box
window.addEventListener('click', clearText );

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.