Pen Settings

HTML

CSS

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

JavaScript

Babel is required to process package imports. If you need a different preprocessor remove all packages first.

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

Behavior

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.

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

              
                <div id=B>
              
            
!

CSS

              
                
              
            
!

JS

              
                ///////////////////////////////////////////////////////////////////////////////
// 1Keys - A 1 Kilobyte JavaScript Piano
// By Frank Force 2020
// https://github.com/KilledByAPixel/1Keys

// How to minify...
// 1. Remove white space, Terser recommended
// 2. Replace " with `
// 3. Regpack, set exception for variable B
// 4. Replace " with Q (or any unused character)
// 5. Put it in <body onload="">

// body style
document.body.style = `background:#112;color:#fff;user-select:none;text-align:center`;
 
// audio context
C = new AudioContext;

// get piano key div
D = i=> eval(`K` + i);

// instrument select
[...`∿🎻🎷🎹`].map((i,j)=>                               // instrument icons
    B.innerHTML += i +                                     // icon
        `<input type=radio name=I checked onmousedown=I=${ // radio input
    3 - j}> `);                                            // instrument select

// piano keys
for( I = i = 0; i < 36; A = []) // 3 x 12 keys, init instrument and sounds array
    B.innerHTML +=
        `${i%12 ? `` : `<br>`                                       // new row
        }<div id=K${                                                // create key
            k = 24 + i%12 - (i/12|0)*12                             // reorder keys
        } style=display:inline-block;margin:2px;background:${       // key style
        `02579`.indexOf(i++%12 - 1) < 0 ?                           // b or w
        `#fff;color:#000;width:60px;height:180px` :                 // white
        `#000;position:absolute;margin-left:-17px;width:33px;height:99px` // black
        } onmouseover=event.buttons&&P(${ k                         // mouse over
        }) onmousedown=P(${ k                                       // mouse down
        }) onmouseup=X(${ k                                         // mouse up
        }) onmouseout=X(${ k                                        // mouse out
        })>`,                                                       // end key div

///////////////////////////////////////////////////////////////////////////////
// sound
      
// play note
P = i=> i < 0 || A[i] || // is valid and note not playing
(
    A[i] = [         // instruments
        [...`1248`], // 🎹 organ
        [...`3579`], // 🎷 brass
        [...`321`],  // 🎻 strings
        [...`3`],    // ∿ sine
    ][ I ].map(j=>(
        o = C.createOscillator(               // create oscillator
            D(i).style.transition = 
                D(i).innerHTML),              // reset transition
        o.connect(                            // oscillator to gain
            o.g = C.createGain(               // create gain node
                o.frequency.value =           // set frequency
                    j * 55 * 2**((i+3)/12)))  // A 55 root note 
        .connect(C.destination),              // gain to destination
        o.g.gain.value = .2/(1+Math.log2(j)), // set gain
        o.start(),                            // start audio
        o)                                    // return sound
    ),
    D(i).b = D(i).style.background, // save original color 
    D(i).style.background = `#f00`  // set key color red
);

// cancel note
X = i=> A[i] &&                                 // is already playing?
    A[i].map(o=>                                // for each oscilator
        setTimeout(i=>o.stop(), 350,            // stop sound after delay
            o.g.gain.linearRampToValueAtTime(   // set gain start ramp
                o.g.gain.value, C.currentTime), // set gain
            o.g.gain.linearRampToValueAtTime(   // ramp off gain
                A[i] = 0, C.currentTime + .3),  // clear note  
            D(i).style.transition = `.5s`,      // set transition
            D(i).style.background = D(i).b));   // reset original color

// stop all sounds if focus lost
onblur = i=> A.map((e,i)=> X(i));

///////////////////////////////////////////////////////////////////////////////
// keyboard controls
// keyboard to piano key mapping
K = `zsxdcvgbhnjm,l.;/q2w3er5t6y7ui9o0p[=]`;

// play note on key down
onkeydown = i=> P(
    K.indexOf(i.key.toLowerCase())                  // map key to note
        - 5 * (K.indexOf(i.key.toLowerCase()) > 16) // overlap 2nd row of keys
);

// release note on key up
onkeyup = i=> X(
    K.indexOf(i.key.toLowerCase())                  // map key to note
        - 5 * (K.indexOf(i.key.toLowerCase()) > 16) // overlap 2nd row of keys
);

// 1Keys By Frank Force - 1020 bytes
//<body onload="for(_='onWtiW~keyQo.!${ZutYin_;marg_^=>FerE;width:Ddown.map((e,o)F.cWnect(._dexOf(;height:;color:#12(Ke.Q.toLowECase())-5*>16)=C.create[...``],3tTimestylealue$(e)..transi~=),A[e]	=eF,C.curren(Zk})!g.ga_.._nEHTML Wmouse,l_earRampToVA(backgroundfor(B.=`:#1fff;usE-select:nWe;text-align:centE`,C=new AudioCWtext,$=iFeval(`K`+i∿🎻🎷🎹`]B+=e+`<_pY type=radio name=I checked=I=Z3-o}> `I=i=0;i<36;A=[])B+=`Zi%?``:`<br>`}<div id=KZk=24+i%-*(i/|0)} =display:_l_e-block^:2;:Z`02579`i++%-1)<0?`#fff000D60180`:`#000;posi~:absolYe^-left:-17D3399`}ovE=event.bYtWs&&P=Pup=XoY=X>`,Pe<0||	||(	=[4857921`]][I]nF(oOscillator(o!gGa_(!frequency.v=55*n*2**((e+3)/)))C.dest_a~v=.2/(1+Math.log2(n)!start(o).b=,=`#f00`);X	&&	oFseoY(eF!stop(350v)	=0+.3`.5s`,=.b)WblurAX(o)K=`zsxdcvgbhnjm,l.;/q2w3E5t6y7ui9o0p[=]`,WQPWQupX)';G=/[-D-F^_YZ!Q~W]/.exec(_);)with(_.split(G))_=join(shift());eval(_)"id=B>
              
            
!
999px

Console