<h1>Morphing Keyboard Keys (test)</h1>
<h2>
  Press and hold the shift key <br />
  or tap the shift key below
</h2>
<div class="keyboard"></div>
<br />
<a href="https://codepen.io/lbebber" target="_blank" class="credit">by Lucas Bebber</a>
body
  text-align center
  margin-top 30px
  font-family 'Helvetica Neue','Helvetica',Arial,sans-serif
  color #111111
  background #fff
h1
  margin-bottom 0
h2
  font-weight normal
  margin-top 5px
.keyboard
  text-align left
  display inline-block
  font-size 30px
.key
  background #eee
  display inline-block
  min-width 40px
  height 50px
  line-height @height
  vertical-align top
  margin-left 2px
  margin-right 2px
  margin-bottom 4px
  position relative
.key-shift
  width 70px
  text-align center
  line-height 50px
  font-size 0.6em
  cursor pointer
  border none 
  padding 0
  outline none
.key-shift-neverpressed
  outline 4px solid #59f !important
.key-pressed
  box-shadow inset 0 4px 2px -2px rgba(0,0,0,0.4)
  background #666
  color #fff
.letter
  position absolute
  width 100%
  height 100%
  line-height 50px
  text-align center
  transform-origin 50% 80%
  t=90ms
  e=ease-out
  transition opacity t*0.5 e, transform t e
  
.credit
  display inline-block
  font-size 0.8em
  margin-top 1em
View Compiled
$(document).ready(function(){
  var keyboard=[
    {
      offset:20,
      keys:['q','w','e',{letter:'r',x:0.4,y:0.2},'t','y','u',{letter:'i',x:0,y:0},'o','p']
    },
    {
      offset:40,
      keys:['a','s',{letter:'d',x:0.2,y:0},{letter:'f',y:0,x:0.4},'g',{letter:'h',x:0.2,y:0},{letter:'j',x:0.6,y:0},'k',{letter:'l',y:0,x:0.6}]
    },
    {
      offset:0,
      shift:true,
      keys:['z','x','c','v','b','n',{letter:'m',x:0,y:0.2}]
    }
  ]
  function renderKeyboard(){
    keyboard.forEach(function(row){
      var $row=$("<div/>")
        .addClass("key-row")
        .css({
          marginLeft:row.offset+"px"
        })
        .appendTo(".keyboard");
      
      if(row.shift){
        var $shift=$("<button/>")
          .addClass("key key-shift key-shift-neverpressed")
          .text("shift")
          .appendTo($row)
      }
      row.keys.forEach(function(keyLetter){
        var letter=keyLetter;
        var sxd=0.2;
        var syd=0.2;
        if(typeof keyLetter=="object"){
          letter=keyLetter.letter;
          sxd=typeof keyLetter.x=="number"?keyLetter.x:sxd;
          syd=typeof keyLetter.y=="number"?keyLetter.y:sxd;
        }
        var $key=$("<div/>")
          .addClass("key key-letter")
          .data("scale-x-delta",sxd)
          .data("scale-y-delta",syd)
          .attr("data-letter",letter)
          .appendTo($row);
        

        
        var $lower=$("<div/>")
          .addClass("letter letter-lowercase")
          .text(letter)
          .appendTo($key);
        
        var $upper=$("<div/>")
          .addClass("letter letter-uppercase")
          .text(letter.toUpperCase())
          .appendTo($key);
      })
    })
  }
  renderKeyboard();
  
  
  var keys=[];
  $(".key-letter").each(function(i){
    
    var $key=$(this);
    var $upper=$key.children(".letter-uppercase");
    var $lower=$key.children(".letter-lowercase");
    var scaleXD=$key.data("scale-x-delta");
    var scaleYD=$key.data("scale-y-delta");
    var upperSX=1-scaleXD;
    var upperSY=1-scaleYD;
    var lowerSX=1+scaleXD;
    var lowerSY=1+scaleYD;
    
    function setKeyUpperCase(){
      $upper.css({
        transform:"scale(1,1) rotateY(0)",
        opacity:1
      });
      $lower.css({
        transform:"scale("+lowerSX+","+lowerSY+") rotateY(0)",
        opacity:0
      });
    }
    
    function setKeyLowerCase(){
      $lower.css({
        transform:"scale(1,1) rotateY(0)",
        opacity:1
      });
      $upper.css({
        transform:"scale("+upperSX+","+upperSY+") rotateY(0)",
        opacity:0
      });
    }
    
    /*var duration=92;
    var delay=i*1.5;
    $key.children(".letter").css({
      transitionDuration:(duration/2)+"ms, "+duration+"ms",
      transitionDelay:delay+"ms"
    });*/
    
    setKeyLowerCase();
    
    keys.push({
      key:$key,
      setLowerCase:setKeyLowerCase,
      setUpperCase:setKeyUpperCase
    });
  });
  
  function callForAllKeys(fName){
    keys.forEach(function(key){
      key[fName]();
    });
  }
  function setLowerCase(){
    callForAllKeys("setLowerCase");
  }
  function setUpperCase(){
    callForAllKeys("setUpperCase");
  }
  var shiftPressed=false;
  function shift(){
    shiftPressed=true;
    setUpperCase();
    $(".key-shift").addClass("key-pressed");
    $(".key-shift-neverpressed").removeClass("key-shift-neverpressed");
  }
  function unshift(){
    shiftPressed=false;
    setLowerCase();
    $(".key-shift").removeClass("key-pressed");
  }
  function toggleShift(){
    shiftPressed?unshift():shift();
  }
  $(document).keydown(function(event){
    if(event.keyCode==16){
      shift();
    }else{
      var char=String.fromCharCode(event.keyCode);
      if(char!=""){
        $(".key-letter[data-letter="+char.toLowerCase()+"]").addClass("key-pressed");
      }
    }
  });
  $(document).keyup(function(event){
    if(event.keyCode==16){
      unshift();
    }else{
      var char=String.fromCharCode(event.keyCode);
      if(char!=""){
        $(".key-letter[data-letter="+char.toLowerCase()+"]").removeClass("key-pressed");
      }
    }
  });
  $(".key-shift").click(function(){
    toggleShift();
  })
  
  
});
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. //cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js