Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

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

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

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.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <p>This code is a sample from <a href="https://github.com/ILuque/keyboard">GitHub repository</a></p>
<div id="progressBar">
  <div id="progressBarValue">
    <p id="levelInfo">level</p>
  </div>
</div>
<div id="warning"></div>
<div id="text">
  <p id="textBase"></p>
  <p id="textTyped"></p>
</div>
<div id="kbWrap" class="center">

  <!-- -   KEYBOARD  - -->

</div>
<footer>
  <p>made by Iker L - GNU General Public License - <a href="https://github.com/ILuque/keyboard">Check it out on github <img id="gitlogo" src="img/octocat.png"></a></p>
</footer>
</body>
              
            
!

CSS

              
                /*! normalize.css v3.0.2 | MIT License | git.io/normalize */

html {
  font-family: sans-serif;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%
}

body {
  margin: 0
}

article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section,
summary {
  display: block
}

audio,
canvas,
progress,
video {
  display: inline-block;
  vertical-align: baseline
}

audio:not([controls]) {
  display: none;
  height: 0
}

[hidden],
template {
  display: none
}

a {
  background-color: transparent
}

a:active,
a:hover {
  outline: 0
}

abbr[title] {
  border-bottom: 1px dotted
}

b,
strong {
  font-weight: 700
}

dfn {
  font-style: italic
}

h1 {
  font-size: 2em;
  margin: .67em 0
}

mark {
  background: #ff0;
  color: #000
}

small {
  font-size: 80%
}

sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline
}

sup {
  top: -.5em
}

sub {
  bottom: -.25em
}

img {
  border: 0
}

svg:not(:root) {
  overflow: hidden
}

figure {
  margin: 1em 40px
}

hr {
  -moz-box-sizing: content-box;
  box-sizing: content-box;
  height: 0
}

pre {
  overflow: auto
}

code,
kbd,
pre,
samp {
  font-family: monospace, monospace;
  font-size: 1em
}

button,
input,
optgroup,
select,
textarea {
  color: inherit;
  font: inherit;
  margin: 0
}

button {
  overflow: visible
}

button,
select {
  text-transform: none
}

button,
html input[type=button],
input[type=reset],
input[type=submit] {
  -webkit-appearance: button;
  cursor: pointer
}

button[disabled],
html input[disabled] {
  cursor: default
}

button::-moz-focus-inner,
input::-moz-focus-inner {
  border: 0;
  padding: 0
}

input {
  line-height: normal
}

input[type=checkbox],
input[type=radio] {
  box-sizing: border-box;
  padding: 0
}

input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
  height: auto
}

input[type=search] {
  -webkit-appearance: textfield;
  -moz-box-sizing: content-box;
  -webkit-box-sizing: content-box;
  box-sizing: content-box
}

input[type=search]::-webkit-search-cancel-button,
input[type=search]::-webkit-search-decoration {
  -webkit-appearance: none
}

fieldset {
  border: 1px solid silver;
  margin: 0 2px;
  padding: .35em .625em .75em
}

legend {
  border: 0;
  padding: 0
}

textarea {
  overflow: auto
}

optgroup {
  font-weight: 700
}

table {
  border-collapse: collapse;
  border-spacing: 0
}

td,
th {
  padding: 0
}


/* ==========================================================================
     -note: "kb" is shorten form of "keyboard" -
   ========================================================================== */


/* === HTML === */

html {
  margin: 5%;
}


/* === BODY === */

body {
  overflow-x: hidden;
  background: #eef;
}


/* === menu === */

#base {
  background-color: #67A560;
  color: white;
}

menu {
  margin: 1em auto;
  width: 44%;
  display: flex;
  padding: 0;
}

menuitem {
  border-radius: 1px;
  border: 1px solid #827777;
  cursor: pointer;
  color: #827777;
  font-size: 0.8em;
  padding: 0.25em 0.5em;
  margin: 0em auto;
}

menuitem:hover {
  background-color: #D5F6BC;
}

menuitem:active {
  position: relative;
  top: 1px;
}


/* === TEXT INPUT aka output /exercise === */

#text {
  border: 3px solid #8888FF;
  min-height: 3em;
  margin: 1em auto;
  padding: 0 1em;
  max-width: 700px;
  background-color: none;
}

#text.mistake {
  background-color: red;
}

#textBase,
#textTyped {
  font-family: Arial, sans-serifS;
}

#textBase {
  position: absolute;
  );
}

#textTyped {
  position: static;
  color: green;
  z-index: 10;
  text-shadow: 0px 0px 4px rgba(13, 255, 0, 1);
}

#textTyped::after {
  /*points next char*/
  content: "_";
  color: #3AA206;
  text-shadow: none;
  text-decoration: underline;
}


/* === KEYBOARD === */

#kbWrap {}

#kbBody {
  background-color: white;
  border-radius: 0.75em;
  padding: 1em;
}


/* === ROW === */

.kbRow {
  background-color: #88f;
  display: flex;
  display: -ms-flexbox;
}

#kbRow_0 {
  margin-bottom: 1em;
}


/* === KEY === */


/*  IMPORTANT:
   note that font-size, height & width are dinamically resized by jS */

.kbKey,
.kbGap {
  /* display: inline-flex; */
  height: 100%;
  /*kbRow height*/
  box-sizing: border-box;
}

.kbGap {
  background-color: darkblue;
}

.kbKey {
  background-color: #a22;
  position: relative;
  /*for absolute possitioning of child nodes: p_tl, etc*/
  border: solid red 1px;
}

.kbKey.pressed {
  background-color: yellow;
}


/* === key animation === */


/* === KEY TEXT === */

.p_tl,
.p_bl,
.p_tr,
.p_br {
  margin: 0px;
  position: absolute;
}

.p_tl {
  top: 0px;
  left: 0px;
}

.p_bl {
  bottom: 0px;
  left: 0px;
}

.p_tr {
  top: 0px;
  right: 0px;
}

.p_br {
  bottom: 0px;
  right: 0px;
}

p.pressed {
  background-color: green;
}


/* === lock key indicators === */

#lockKeyIndicator {}

#capsLockInd,
#numLockInd,
#scrollLockInd {
  width: 30%;
  display: inline-block;
}


/* level/progress bar*/

#progressBar {
  min-width: 5em;
  max-width: 450px;
  margin: 1em auto;
  height: 1em;
  border: 1px solid #aaa;
  border-radius: 2px;
}

#progressBarValue {
  margin: 0;
  min-width: 5em;
  max-width: 100%;
  height: 1em;
  background-color: #67A560;
  color: #1F5A02;
  position: relative;
}

#levelInfo {
  margin: 0;
  position: absolute;
  right: 5px;
}


/* === warning msg === */

#warning {
  position: absolute;
  width: 100%;
  text-align: center;
  font-size: 4em;
  color: rgba(158, 0, 0, 0.4);
  z-index: 10;
  opacity: 0;
  /* <-- */
  transition: opacity 1s;
  -moz-transition: opacity 1s;
  -webkit-transition: opacity 1s;
  -o-transition: opacity 1s;
}

#warning.showWarning {
  opacity: 1;
}


/* ==== FOOTER ==== */

footer {
  /* background: black; */
  height: 3em;
  margin-top: 2em;
  color: #999;
  padding: 1em;
  width: 100%;
  /* position: absolute; */
  /* bottom: 0; */
  z-index: -1;
}

footer p {
  text-align: center;
}

footer img {
  height: 2em;
  vertical-align: middle;
}


/* ==========================================================================
   Media Queries
   ========================================================================== */


/* ==========================================================================
     Slighty stylized as a Mac keyboard would look like
   ========================================================================== */


/* === menu === */

#mac {
  background-color: #67A560;
  color: white;
}

#base {
  background-color: transparent;
  color: #827777;
}


/* === KEYBOARD === */

#kbRow_0 {
  position: relative;
  display: inline-block;
  margin: 0px;
}

#kbRow_0 > .kbKeyWrap {
  height: 70% !important;
  position: relative;
  display: inline-block;
  bottom: 0px;
  overflow: hidden;
}

#kbRow_0 > .kbGap {
  width: 0px !important;
}

#kbWrap {}

#kbBody {
  border-left: 0.1em #808080 solid;
  border-bottom: 0.1em rgb(101, 101, 101) solid;
  background: #BFBFBF;
  /* For browsers that do not support gradients */
  background: -webkit-linear-gradient(bottom, #BFBFBF, #E8E8E8);
  /* For Safari 5.1 to 6.0 */
  background: -o-linear-gradient(top, #BFBFBF, #E8E8E8);
  /* For Opera 11.1 to 12.0 */
  background: -moz-linear-gradient(top, #BFBFBF, #E8E8E8);
  /* For Firefox 3.6 to 15 */
  background: linear-gradient(to top, #BFBFBF, #E8E8E8);
  /* Standard syntax (must be last) */
}


/* === ROW === */

.kbRow {
  background-color: transparent;
}


/* === KEY === */


/*  IMPORTANT:
   note that font-size, height & width are dinamically resized by jS */

.kbKey,
.kbGap {}

.kbGap {
  background-color: transparent;
  display: inline-block;
}

.kbKeyWrap {
  /* display: inline-block;
    border: 0.2em solid transparent;
    box-sizing:border-box;
    background: black; */
  border-radius: 4px;
}

.kbKey {
  position: relative;
  border-right: solid #777 0.1em;
  border-bottom: solid #777 0.1em;
  border-left: solid #777 0.1em;
  border-top: solid #777 0.1em;
  border-radius: 0.4em;
  background-color: rgb(237, 237, 237);
  box-shadow: -0.05em 0.1em 0em 0.2px rgb(149, 148, 148);
  box-sizing: border-box;
  height: 90%;
}

.kbKey.pressed {
  background-color: #EDEDED;
  top: 0.1em;
  box-shadow: none;
}


/* === key animation === */


/* === KEY TEXT === */

.p_tl,
.p_bl,
.p_tr,
.p_br {
  margin: 0.1em;
  overflow: hidden;
}

.p_tl {
  top: 0px;
  left: 0px;
  overflow: hidden;
}

.p_bl {
  bottom: 0px;
  left: 0px;
}

.p_tr {
  top: 0px;
  right: 0px;
}

.p_br {
  bottom: 0px;
  right: 0px;
}

p.pressed {
  background-color: transparent;
}


/* === lock key indicators === */

#lockKeyIndicator {}

#capsLockInd,
#numLockInd,
#scrollLockInd {
  width: 30%;
  display: inline-block;
}


/* ==========================================================================
     style for an old windows keyboard
   ========================================================================== */


/* === menu === */

#win {
  background-color: #67A560;
  color: white;
}

#base {
  background-color: transparent;
  color: #827777;
}


/* === KEYBOARD === */

#kbWrap {}

#kbBody {
  border-bottom: 0.5em #808080 solid;
  border-left: 0.2em #808080 solid;
  border-right: 0.2em #808080 solid;
  border-top: 0.3em rgb(211, 204, 204) solid;
  /* For Safari 5.1 to 6.0 */
  border-bottom: radial-gradient(red 5%, yellow 15%, green 60%);
}


/* === ROW === */

.kbRow {
  background-color: transparent;
}


/* === KEY === */


/*  IMPORTANT:
   note that font-size, height & width are dinamically resized by jS */

.kbKey,
.kbGap {}

.kbRow .kbGap {
  /*    background-color: transparent;
    -webkit-box-shadow: -5px 0px 0px 0px rgb(243, 243, 243);
    -moz-box-shadow: -5px 0px 0px 0px rgb(243, 243, 243);
    box-shadow: -5px 0px 0px 0px rgb(243, 243, 243);*/
}

.kbKeyWrap {
  background: #929292;
  -webkit-box-shadow: -8px 6px 22px 1px rgb(181, 180, 180);
  -moz-box-shadow: -8px 6px 22px 1px rgb(181, 180, 180);
  box-shadow: -8px 6px 22px 1px rgb(181, 180, 180);
}

.kbRow>.kbKeyWrap:first-of-type {
  border-radius: 0.4em;
}

.kbKey {
  /* display: none; */
  margin: 0.5px;
  border-top: rgb(209, 209, 209) 0.3em solid;
  border-left: #9B9A9A 0.5em solid;
  border-bottom: #B9B9B9 0.7em solid;
  border-right: #ddd 0.2em solid;
  border-radius: 0.4em;
  background-color: #fcfcfc;
  color: #292929;
  position: relative;
  top: -0.1em;
  z-index: 2;
  -webkit-box-shadow: -1px 1px 0px 0px rgba(77, 77, 77, 1);
  -moz-box-shadow: -1px 1px 0px 0px rgba(77, 77, 77, 1);
  box-shadow: -1px 1px 0px 0px rgba(77, 77, 77, 1);
  background: -webkit-radial-gradient(red 5%, yellow 15%, green 66%);
  /* Safari 5.1-6.0 */
  background: -o-radial-gradient(red 5%, yellow 15%, green 66%);
  /* For Opera 11.6 to 12.0 */
  background: -moz-radial-gradient(red 5%, yellow 15%, green 66%);
  /* For Firefox 3.6 to 15 */
  background: linear-gradient( #E6E6E6 16%, #fff 66%);
  /* Standard syntax (must be last) */
}

.kbKey.pressed {
  background-color: #fcfcfc;
  top: 0.1em;
  hola left: -0.1em;
  z-index: 1;
}


/* === key animation === */


/* === KEY TEXT === */

.p_tl,
.p_bl,
.p_tr,
.p_br {
  margin: 0.1em;
}

p.pressed {
  background-color: transparent;
}


/* === lock key indicators === */

#lockKeyIndicator {}

#capsLockInd,
#numLockInd,
#scrollLockInd {
  width: 30%;
  display: inline-block;
}
              
            
!

JS

              
                /* 
 **    var kbLayour:  A variable where to store different keyboard layouts (different languages)
 **    var keytable:  Values of each keys
 ** note the using of globals is not a best practice
 */

/*  = Codification =
 **  Keys and gaps are stored in array values:
 **  "A"             means key A
 **  "gap:2"         means a phisical GAP on the kb 2 times regular key size
 **  "w:1.5, Tab"    means "Tab" key which has a WIDTH of 1.5 times regular one
 **  "h:2, Intro"    means "Intro" key which has a HEIGHT 2 times regular one
 */

var kbLayout = {
  "ENG": {
    "language": "english",
    "row": [
      [{
        "tl": "Esc"
      }, {
        "gap": 1
      }, {
        "tl": "F1"
      }, {
        "tl": "F2"
      }, {
        "tl": "F3"
      }, {
        "tl": "F4"
      }, {
        "gap": 0.5
      }, {
        "tl": "F5"
      }, {
        "tl": "F6"
      }, {
        "tl": "F7"
      }, {
        "tl": "F8"
      }, {
        "gap": 0.5
      }, {
        "tl": "F9"
      }, {
        "tl": "F10"
      }, {
        "tl": "F11"
      }, {
        "tl": "F12"
      }, {
        "gap": 0.5
      }, {
        "tl": "PrtSc"
      }, {
        "tl": "Scroll"
      }, {
        "tl": "Paus."
      }, {
        "gap": 0.5
      }],
      [{
        "tl": "~",
        "bl": "`"
      }, {
        "tl": "!",
        "bl": "1"
      }, {
        "tl": "@",
        "bl": "2"
      }, {
        "tl": "#",
        "bl": "3"
      }, {
        "tl": "$",
        "bl": "4"
      }, {
        "tl": "%",
        "bl": "5"
      }, {
        "tl": "^",
        "bl": "6"
      }, {
        "tl": "&",
        "bl": "7"
      }, {
        "tl": "*",
        "bl": "8"
      }, {
        "tl": "(",
        "bl": "9"
      }, {
        "tl": ")",
        "bl": "0"
      }, {
        "tl": "_",
        "bl": "-"
      }, {
        "tl": "+",
        "bl": "="
      }, {
        w: 2,
        "tl": "Backspace"
      }, {
        "gap": 0.5
      }, {
        "tl": "Insert"
      }, {
        "tl": "Home"
      }, {
        "tl": "PgUp"
      }, {
        "gap": 0.5
      }, {
        "tl": "Num Lock"
      }, {
        "tl": "/"
      }, {
        "tl": "*"
      }, {
        "tl": "-"
      }],
      [{
        "w": 1.5,
        "tl": "Tab"
      }, {
        "tl": "Q"
      }, {
        "tl": "W"
      }, {
        "tl": "E"
      }, {
        "tl": "R"
      }, {
        "tl": "T"
      }, {
        "tl": "Y"
      }, {
        "tl": "U"
      }, {
        "tl": "I"
      }, {
        "tl": "O"
      }, {
        "tl": "P"
      }, {
        "tl": "{",
        "bl": "["
      }, {
        "tl": "}",
        "bl": "]"
      }, {
        w: 1.5,
        "tl": "|",
        "bl": "\\"
      }, {
        "gap": 0.5
      }, {
        "tl": "Del"
      }, {
        "tl": "End"
      }, {
        "tl": "PgDn"
      }, {
        "gap": 0.5
      }, {
        "tl": "7 ",
        "bl": "Home "
      }, {
        "tl": "8 ",
        "bl": "↑ "
      }, {
        "tl": "9 ",
        "bl": "PgUp "
      }, {
        h: 2,
        "tl": "+ "
      }],
      [{
        "w": 1.75,
        "tl": "Caps Lock"
      }, {
        "tl": "A"
      }, {
        "tl": "S"
      }, {
        "tl": "D"
      }, {
        "tl": "F"
      }, {
        "tl": "G"
      }, {
        "tl": "H"
      }, {
        "tl": "J"
      }, {
        "tl": "K"
      }, {
        "tl": "L"
      }, {
        "tl": ":",
        "bl": ";"
      }, {
        "tl": "\"",
        "bl": "'"
      }, {
        w: 2.25,
        "tl": "Enter "
      }, {
        "gap": 4
      }, {
        "tl": "4 ",
        "bl": "← "
      }, {
        "tl": "5 "
      }, {
        "tl": "6 ",
        "bl": "→ "
      }],
      [{
        w: 2.25,
        "tl": "Shift"
      }, {
        "tl": "Z"
      }, {
        "tl": "X"
      }, {
        "tl": "C"
      }, {
        "tl": "V"
      }, {
        "tl": "B"
      }, {
        "tl": "N"
      }, {
        "tl": "M"
      }, {
        "tl": "<",
        "bl": ", "
      }, {
        "tl": ">",
        "bl": "."
      }, {
        "tl": "?",
        "bl": "/"
      }, {
        w: 2.75,
        "tl": "Shift "
      }, {
        "gap": 1.5
      }, {
        "tl": "↑"
      }, {
        "gap": 1.5
      }, {
        "tl": "1 ",
        "bl": "End "
      }, {
        "tl": "2 ",
        "bl": "↓ "
      }, {
        "tl": "3 ",
        "bl": "PgDn "
      }, {
        h: 2,
        "tl": "Enter "
      }],
      [{
        w: 1.25,
        "tl": "Ctrl"
      }, {
        w: 1.25,
        "tl": "Win"
      }, {
        w: 1.25,
        "tl": "Alt"
      }, {
        w: 6.25,
        "tl": " "
      }, {
        w: 1.25,
        "tl": "Alt "
      }, {
        w: 1.25,
        "tl": "Win "
      }, {
        w: 1.25,
        "tl": "Menu"
      }, {
        w: 1.25,
        "tl": "Ctrl "
      }, {
        "gap": 0.5
      }, {
        "tl": "←"
      }, {
        "tl": "↓"
      }, {
        "tl": "→"
      }, {
        "gap": 0.5
      }, {
        w: 2,
        "tl": "0 ",
        "bl": "Ins "
      }, {
        "tl": ". ",
        "bl": "Del "
      }]
    ]
  },
  "ESP": {
    "language": "spanish",
    "row": [
      [{
        "tl": "Esc"
      }, {
        "gap": 1
      }, {
        "tl": "F1"
      }, {
        "tl": "F2"
      }, {
        "tl": "F3"
      }, {
        "tl": "F4"
      }, {
        "gap": 0.5
      }, {
        "tl": "F5"
      }, {
        "tl": "F6"
      }, {
        "tl": "F7"
      }, {
        "tl": "F8"
      }, {
        "gap": 0.5
      }, {
        "tl": "F9"
      }, {
        "tl": "F10"
      }, {
        "tl": "F11"
      }, {
        "tl": "F12"
      }, {
        "gap": 0.5
      }, {
        "tl": "PrtSc"
      }, {
        "tl": "Scroll Lock"
      }, {
        "tl": "Pause",
        "bl": "Break"
      }],
      [{
        "tl": "ª",
        "bl": "º",
        "br": "\\"
      }, {
        "tl": "!",
        "bl": "1",
        "br": "|"
      }, {
        "tl": "@",
        "bl": "2"
      }, {
        "tl": "#",
        "bl": "3"
      }, {
        "tl": "$",
        "bl": "4"
      }, {
        "tl": "%",
        "bl": "5"
      }, {
        "tl": "^",
        "bl": "6"
      }, {
        "tl": "&",
        "bl": "7"
      }, {
        "tl": "*",
        "bl": "8"
      }, {
        "tl": "(",
        "bl": "9"
      }, {
        "tl": ")",
        "bl": "0"
      }, {
        "tl": "_",
        "bl": "-"
      }, {
        "tl": "+",
        "bl": "="
      }, {
        w: 2,
        "tl": "Backspace"
      }, {
        "gap": 0.5
      }, {
        "tl": "Insert"
      }, {
        "tl": "Home"
      }, {
        "tl": "PgUp"
      }, {
        "gap": 0.5
      }, {
        "tl": "Num Lock"
      }, {
        "tl": "/"
      }, {
        "tl": "*"
      }, {
        "tl": "-"
      }],
      [{
        w: 1.5,
        "tl": "Tab"
      }, {
        "tl": "Q"
      }, {
        "tl": "W"
      }, {
        "tl": "E"
      }, {
        "tl": "R"
      }, {
        "tl": "T"
      }, {
        "tl": "Y"
      }, {
        "tl": "U"
      }, {
        "tl": "I"
      }, {
        "tl": "O"
      }, {
        "tl": "P"
      }, {
        "tl": "{",
        "bl": "["
      }, {
        "tl": "}",
        "bl": "]"
      }, {
        w: 1.5,
        "tl": "|",
        "bl": "\\"
      }, {
        "gap": 0.5
      }, {
        "tl": "Del"
      }, {
        "tl": "End"
      }, {
        "tl": "PgDn"
      }, {
        "gap": 0.5
      }, {
        "tl": "7",
        "bl": "Home"
      }, {
        "tl": "8",
        "bl": "↑"
      }, {
        "tl": "9",
        "bl": "PgUp"
      }, {
        h: 2,
        "tl": "+"
      }],
      [{
        w: 1.75,
        "tl": "Caps Lock"
      }, {
        "tl": "A"
      }, {
        "tl": "S"
      }, {
        "tl": "D"
      }, {
        "tl": "F"
      }, {
        "tl": "G"
      }, {
        "tl": "H"
      }, {
        "tl": "J"
      }, {
        "tl": "K"
      }, {
        "tl": "L"
      }, {
        "tl": "Ñ"
      }, {
        "tl": "&_quot;",
        "bl": "&_#39;"
      }, {
        w: 2.25,
        "tl": "Enter "
      }, {
        "gap": 4
      }, {
        "tl": "4",
        "bl": "←"
      }, {
        "tl": "5"
      }, {
        "tl": "6",
        "bl": "→"
      }],
      [{
        w: 2.25,
        "tl": "Shift"
      }, {
        "tl": "Z"
      }, {
        "tl": "X"
      }, {
        "tl": "C"
      }, {
        "tl": "V"
      }, {
        "tl": "B"
      }, {
        "tl": "N"
      }, {
        "tl": "M"
      }, {
        "tl": "<",
        "bl": ", "
      }, {
        "tl": ">",
        "bl": "."
      }, {
        "tl": "?",
        "bl": "/"
      }, {
        w: 2.75,
        "tl": "Shift "
      }, {
        "gap": 1.5
      }, {
        "tl": "↑"
      }, {
        "gap": 1.5
      }, {
        "tl": "1",
        "bl": "End"
      }, {
        "tl": "2",
        "bl": "↓"
      }, {
        "tl": "3",
        "bl": "PgDn"
      }, {
        h: 2,
        "tl": "Enter"
      }],
      [{
        w: 1.25,
        "tl": "Ctrl"
      }, {
        w: 1.25,
        "tl": "Win"
      }, {
        w: 1.25,
        "tl": "Alt"
      }, {
        w: 6.25,
        "tl": " "
      }, {
        w: 1.25,
        "tl": "Alt "
      }, {
        w: 1.25,
        "tl": "Win "
      }, {
        w: 1.25,
        "tl": "Menu"
      }, {
        w: 1.25,
        "tl": "Ctrl "
      }, {
        "gap": 0.5
      }, {
        "tl": "←"
      }, {
        "tl": "↓"
      }, {
        "tl": "→"
      }, {
        "gap": 0.5
      }, {
        w: 2,
        "tl": "0",
        "bl": "Ins"
      }, {
        "tl": ".",
        "bl": "Del"
      }]
    ]
  }
};

var keyTable = { // keys id.
  //from https://css-tricks.com/snippets/javascript/javascript-keycodes/
  "Backspace": 8,
  "Tab": 9,
  "Enter": 13,
  "Shift": 16,
  "Ctrl": 17,
  "Alt": 18,
  "Pause Break": 19,
  "Caps Lock": 20,
  "Esc": 27,
  " ": 32,
  "PgUp": 33,
  "PgDn": 34,
  "End": 35,
  "Home": 36,
  "→": 37,
  "↑": 38,
  "→": 39,
  "↓": 40,
  "Insert": 45,
  "Del": 46,
  "0": 48,
  "1": 49,
  "2": 50,
  "3": 51,
  "4": 52,
  "5": 53,
  "6": 54,
  "7": 55,
  "8": 56,
  "9": 57,
  "a": 65,
  "b": 66,
  "c": 67,
  "d": 68,
  "e": 69,
  "f": 70,
  "g": 71,
  "h": 72,
  "i": 73,
  "j": 74,
  "k": 75,
  "l": 76,
  "m": 77,
  "n": 78,
  "o": 79,
  "p": 80,
  "q": 81,
  "r": 82,
  "s": 83,
  "t": 84,
  "u": 85,
  "v": 86,
  "w": 87,
  "x": 88,
  "y": 89,
  "z": 90,
  "Win": 91,
  "Win ": 92,
  "select key": 93, //<-- o.O  I have never seen it
  "0 ": 96,
  "1 ": 97,
  "2 ": 98,
  "3 ": 99,
  "4 ": 100,
  "5 ": 101,
  "6 ": 102,
  "7 ": 103,
  "8 ": 104,
  "9 ": 105,
  "* ": 106,
  "+ ": 107,
  "- ": 109,
  "decimal point": 110, // <-is not the same than period? full stop? (190)
  "/ ": 111,
  "F1": 112,
  "F2": 113,
  "F3": 114,
  "F4": 115,
  "F5": 116,
  "F6": 117,
  "F7": 118,
  "F8": 119,
  "F9": 120,
  "F10": 121,
  "F11": 122,
  "F12": 123,
  "Num Lock": 144,
  "Scroll Lock": 145,
  "; ": 186,
  "= ": 187,
  ", ": 188,
  "_ ": 189,
  ". ": 190,
  "/ ": 191,
  "´ ": 192,
  "{ ": 219,
  "\\ ": 220,
  "} ": 221,
  "' ": 222
};

var level = [ //level[x]sublevel[y]
  {
    "levelNumber": 1,
    "keys": ["a", "s", "d", "f"],
    "subLevel": [
      "asd a a s d",
      "asdf jkl a s k j l aj lk kj as kj lk",
      "gh jkl a kd fjk lk sdlk h hksdg lkh g"
    ]
  }, {
    "levelNumber": 2,
    "keys": ["a", "s", "d", "f", "j", "k", "l"],
    "subLevel": [
      "as we are alies we do yahoo",
      "quo two jar of jade relay rely real liar",
      "the Satelite was A Waste of Port Louisse war"
    ]
  }, {
    "levelNumber": 3,
    "keys": ["a", "s", "d", "f", "q", "w", "e", "r", "r", "o", "i", "v", "n", "x", "c", "g"],
    "subLevel": [ /* levelNumber 2 */
      "there is a happy keyboard on the hill",
      "Dracula lives in a castle. He goes out at night.",
      "Lorem ipsum dolor sit amet, consectetur number 1"
    ]
  }, {
    "levelNumber": 4,
    "keys": ["all"],
    "subLevel": [
      "3, 2, 1,... CONGRATULATIONS.  This is the end!"
    ]
  }
];

/*  Main script */
/*  Main script */

/*   GAME FLOW:
 **   game state deppending on state of localStorage variables
 **   onload: check if previus levels were played and restore/start game
 **   end of level: save users level and set next level
 */

//TODO: wrap all in a function- namespace
//TODO:  FOCUS ON KEYBOARD
//TODO: Do not show to the user the keyboards pressed o keyboard when they are out of alphabet:
//          some keys are not recogniced properly.

//;(function (){  // namespace

/* on screen keyboard "kb" */
function drawKb(kbLang) {
  "use strict";
  if (kbLang === undefined) {
    kbLang = "ENG";
  }
  var i, j; //loops aux
  var keyWidth, keyHeight, fontSize; // JS responsive

  $('#kbWrap').append("<div id='kbBody' ></div>");

  /*responsive: initialize px sizes*/
  keyWidth = parseInt($("#kbBody").width() / 23); //23 keys in a full row
  keyHeight = keyWidth;
  fontSize = keyWidth * 0.25;

  /* bucle 1: Rows.  Bucle 2: keys & Gaps */
  for (i = 0; i < kbLayout[kbLang].row.length; i += 1) {
    $("#kbBody").append("<div class='kbRow' id='kbRow_" + i + "' > </div>");
    for (j = 0; j < kbLayout[kbLang].row[i].length; j += 1) {
      drawKey(kbLayout[kbLang].row[i][j], i, keyWidth);
    }
  }

  /*  responsive for each key
   **  kbKey & .kbGap ( WIDTH & HEIGHT ) checked for each key in drawkey()
   */
  $(".kbRow").css("height", keyHeight);
  $(".kbKey").css("font-size", fontSize);

  function drawKey(key, row) { //draws keys (or gaps)
    if (key.hasOwnProperty("gap")) {
      $('#kbRow_' + row).append('<div class="kbGap"></div>');
      $(".kbGap").last().css("width", (keyWidth * key.gap + "px"));
    } else {
      var keyId, lastDiv;
      $('#kbRow_' + row).append('<div class="kbKeyWrap"><div class="kbKey"></div></div>');
      lastDiv = $(".kbKey").last();
      /* mouse events*/
      $(lastDiv).mousedown(function() {
        $(lastDiv).addClass("pressed");
        //console.info(key.tl);
        outputChar(key.tl.toLowerCase());
      });
      $(lastDiv).mouseup(function() {
        $(lastDiv).removeClass("pressed");
      });

      /*a condition for each of the 4  positions of the key */
      if (key.hasOwnProperty("tl")) { //top-left
        //keyId = #ascii. else = key name. ie:"space"/"Alt"/"F10"...
        if (key.tl.length === 1) {
          keyId = key.tl.charCodeAt(0);
        } else {
          keyId = keyTable[key.tl];
        }
        lastDiv.append("<p class='p_tl' id='key_" + keyId + "'>" +
          key.tl + "</p>");
      }
      if (key.hasOwnProperty("bl")) { //bottom-left
        if (key.bl.length === 1) {
          keyId = key.bl.charCodeAt(0);
        } else {
          keyId = keyTable[key.bl];
        }
        lastDiv.append("<p class='p_bl' id='key_" + keyId + "'>" +
          key.bl + "</p>");
      }
      if (key.hasOwnProperty("tr")) { //top-right
        if (key.tr.length === 1) {
          keyId = key.tr.charCodeAt(0);
        } else {
          keyId = keyTable[key.tr];
        }
        lastDiv.append("<p class='p_tr' id='key_" + keyId + "'>" +
          key.tr + "</p>");
      }
      if (key.hasOwnProperty("br")) { //bottom-right
        if (key.br.length === 1) {
          keyId = key.br.charCodeAt(0);
        } else {
          keyId = keyTable[key.br];
        }
        lastDiv.append("<p class='p_br' id='key_" + keyId + "'>" +
          key.br + "</p>");
      }
      /* key width */
      if (key.hasOwnProperty("w")) { //for non-regular size keys.
        // ie:Enter, Spacebar,etc
        // key.w stores "X times the regular size" ie: 2.25
        lastDiv.parent().css("width", (keyHeight * key.w + "px"));
      } else { //regular keys
        lastDiv.parent().css("width", (keyHeight + "px"));
      }
      /* non-regular keys height. ie: Enter & "+"(at the numeric kb)*/
      if (key.hasOwnProperty("h")) {
        lastDiv.parent().css("height", (keyHeight * key.h + "px"));
      } else { //regular keys
        lastDiv.parent().css("height", (keyHeight + "px"));
      }
    }
  } // end  drawKey()

  /* top-right lock keys indicator (windows kb)

  //TODO

  //draws caps lock on top right - it draws ok, but not "led" indicator yet
      (function lockKeyIndicator(){
          $('#kbRow_0').append("<div id = 'lockKeyIndicator'>" +
              "<div id = 'capsLockInd'>Caps Lock</div> " +
              "<div id = 'numLockInd'>Num Lock</div> " +
              "<div id = 'scrollLockInd'>Scroll Lock</div> " +
             "</div>");
          $('#lockKeyIndicator').css({
                  "font-size": fontSize/2,
                  "margin-left": keyWidth/2,
                  "width": keyWidth*4,
                  "height": keyHeight,
                  "line-height": keyHeight + "px",
              });
      })();
  */

}

var user = {
  level: 1,
  sublevel: 1,
  urPossition: 0, //position at the exercise user is doing
  subLvLength: 0, //lenght (num of chars) to do on exercise
  kbLang: "ENG"

};

/* events*/
/* A: mouse clicks*/

//Done at the moment of creation of the keys

/* B: key strokes*/

$(document).on('keypress', function(e) {
  var keyCode = e.keyCode || e.which; //cross-browser solution
  var keyId = String.fromCharCode(keyCode);
  //if Caps_Lock on. in case gets [de]activated outside window object
  if (keyId.toUpperCase() === keyId && keyId.toLowerCase() !== keyId && !e.shiftKey) {
    warning("Caps Lock on");
    animateKey(20, "down");

  } else {
    //warning("Caps Lock off");
    animateKey(20, "up");
  }
  //console.log("key pressed. keycode: " + keyCode);
  outputChar(keyId);
});

$(document).on('keydown', function(e) {

  var keyCode = e.keyCode || e.which;
  //  9->tab , 32->space, 116->F5 , 34->Pg down , 8->backspace
  if ($.inArray(keyCode, [9, 32, 116, 34, 8]) != -1) {
    if (keyCode === 116) {
      warning("F5 update behaviour disabled");
    }
    //write the space before stopping its progation (scrolling)
    if (keyCode === 32) {
      outputChar(" ");
    }
    //stops default action
    (e.preventDefault) ? e.preventDefault(): (e.returnValue = false);
  }
  if (keyCode === 20) { //caps l ock
    animateKey(20, "toggle");
  } else {
    animateKey(keyCode, "down");
  }
  //console.log("---\nkey down. keycode: " + keyCode); //TEST
});

$(document).on('keyup', function(e) {
  var keyCode = (e.keyCode || e.which); //cross-browser solution
  var keyId = String.fromCharCode(keyCode);
  //keyId = keyId.toUpperCase().charCodeAt(); //no lower case
  //console.log("key up. keycode: " + keyCode);
  if (keyCode !== 20) { //Caps-lock
    animateKey(keyCode, "up");
  }
  //animateKey(keyCode,"up"); //true:key down, false:key up
});

/* actions */

function animateKey(keyId, direction) {
  /* keydown & key up may be trigered several times on a kyestroke*/
  if (direction === "down") { //true:key down, false:key up
    $("#key_" + keyId).addClass("pressed");
    $("#key_" + keyId).parent().addClass("pressed");
  } else if (direction === "up") {
    $("#key_" + keyId).removeClass("pressed");
    $("#key_" + keyId).parent().removeClass("pressed");
  } else if (direction === "toggle") {
    $("#key_" + keyId).toggleClass("pressed");
    $("#key_" + keyId).parent().toggleClass("pressed");
  } else if (direction === "press") {
    /*
            $("#key_" + keyId).addClass("pressed");
            $("#key_" + keyId).parent().addClass("pressed");
            setTimeout(function(){
                $("#key_" + keyId).removeClass("pressed");
                $("#key_" + keyId).parent().removeClass("pressed");
                }, 150);*/
  }
}

/* main */

window.onload = (function() {
  "use strict";

  if (typeof(Storage) === "undefined") {
    warning("no local storage");
    console.info("No web storage. Game progress will not be saved.");
  } else if (localStorage.getItem("kbUser") === undefined || localStorage.getItem("kbUser") === null) {
    console.info("Starting a new game.");
    localStorage.kbUser = JSON.stringify(user);
    warning("welcome");
  } else {
    warning("resume");
    user = JSON.parse(localStorage.kbUser);
    console.info("You are at the last level you tried");
    user.urPossition = 0;
  }
  displayExercise(user.level, user.sublevel);
  displayLevel(user.level, user.sublevel);
  drawKb(user.kbLang);

});

/* responsive on resize*/
window.onresize = (function() {
  "use strict";
  $("#kbBody").remove();
  drawKb();
});
/* end of current level (& start of next one) */

function endOfExercise() {
  /* Manages the users, game flow:
   **  at the end of the game, erases level, and call starOfExercise()
   **  shows messages to the user
   */
  warning("END");
  console.info("end of level");
  //if last sublevel
  if (level[user.level - 1].subLevel[user.sublevel - 1 + 1] === undefined) {
    user.subLevel = 1;
    warning("end of level" + user.level);
    user.level += 1;
    //if last level
    if (level[user.level - 1].subLevel[user.sublevel - 1] === undefined) {
      warning("END OF GAME. CONGRATULATIONS");
      console.info("END OF GAME.");
    }
  } else {
    user.sublevel += 1;
  }
  user.urPossition = 0;
  user.subLvLength = 0;
  //ERASE old & show new exercise
  $("#textBase").text("");
  $("#textTyped").text("");
  startOfExercise();
}

function startOfExercise() {
  /* just loads new level*/
  displayExercise(user.level, user.sublevel);
  displayLevel(user.level, user.sublevel);
}

/* output */

function outputChar(typed) {
  //todo
  var hasToType = level[user.level - 1].subLevel[user.sublevel - 1].charAt(user.urPossition);
  //initialize length of the current sublevel's exercise string
  if (user.urPossition === 0) {
    user.subLvLength = level[user.level - 1].subLevel[user.sublevel - 1].length;
  }
  if (typed === hasToType) {
    //console.info("good");
    $("#textTyped").append(typed);
    if (user.urPossition + 1 === user.subLvLength) {
      endOfExercise();
    } else {
      user.urPossition += 1;
    }

  } else {
    warning("wrong");
    mistake();
  }
}

function displayExercise(lv, subLv) {
  $("#textBase").append(level[lv - 1].subLevel[subLv - 1]);

}

/*level indicator at progressBar*/

function displayLevel(lv, subLv) {
  var percentage;
  var step = 8.4; //% of total each sublevel is.  8.4 = 100/12 sublevels
  percentage = ((lv - 1) * 3 + subLv) * step;
  $("#levelInfo").html("level: " + lv + "·" + subLv);
  $('#progressBarValue').animate({
    width: percentage + "%"
  });
}

/* notifications */
//TODO.  INSTEAD OF setTimeOut  -> css animation
function warning(msg) {
  $("#warning").text(msg); // opacity:0
  $("#warning").addClass('showWarning'); //opacity:1
  setTimeout(function() {
    $("#warning").removeClass('showWarning');
  }, 1500);
}

function mistake() {
  $("#text").addClass('mistake'); //opacity:1
  setTimeout(function() {
    $("#text").removeClass('mistake');
  }, 150);
}

//swap style sheet

//} )();

function swapStyleSheet(sheet) {
  /* calls drawKb again as kb size may change (borders and margins)*/
  $("#kbBody").remove();
  if (sheet === undefined) {
    document.getElementById('pageStyle').setAttribute('href', "");
  } else {
    document.getElementById('pageStyle').setAttribute('href', sheet);
  }
  /** if called inmediately, DOM may have unwanted behaviour
   ** tested in chrome. DOM still have the elements with old parameters.
   */
  setTimeout(drawKb, 50);
}
              
            
!
999px

Console