<!--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>
<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>
    <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>
    <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>
    <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>
    <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>
    </div>
  </div>
</div>
<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++){
  originalShifterArray.push(changeKeys[i].innerHTML);
}

//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);
  
  keys.classList.add('pressed');
  
  
  if(!charPressed){
    theTextBox.innerHTML = "Sorry, this pen doesn't work in your browser. :( <br> Try Chrome, Firefox or Opera.";
    return;
  }
  
  //If the user presses CapsLock or Shift, make the alphabetical keys uppercase
  if (charPressed == 'CapsLock' || charPressed == 'Shift') {
    allTheKeys.classList.add('uppercase');
  } 
  //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){
    console.log(theTextBox.innerHTML);
    if(theTextBox.innerHTML.endsWith('<br>')){
      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'){
    if(shiftKey.classList.contains('pressed')){
      clearText();
    } 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){
    e.preventDefault();
    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; 
  console.log(keyDepressed);
  const keys = document.getElementById(keyDepressed);
  console.log(keys);
  
  keys.classList.remove('pressed');
  //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')) {
    allTheKeys.classList.remove('uppercase');
  }
  //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.