Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation


Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

HTML Settings

Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

              <!--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;
 * 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 );
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.