Design and Code a Playable Piano with Figma, HTML, SCSS, and JavaScript
Tags: design, css, javascript, frontend
Published: 2023-12-11 17:29:17

## Introduction to the Digital Piano Project

Welcome to an exciting journey through the world of web development and design, as I share my experience in creating a digital piano from scratch. This project is more than just a showcase of technical skills; it's a vivid illustration of how creativity and coding can harmoniously intertwine to bring a digital masterpiece to life. 

Whether you're a seasoned developer, a design enthusiast, or someone curious about the intricacies of web development, this tutorial is designed to provide valuable insights, practical tips, and a bit of inspiration. Let’s dive into the fascinating process of transforming a simple idea into an interactive and visually appealing digital piano.



If you want to watch the video instead, you can watch it by clicking the YouTube video below:

{% embed https://youtu.be/W3bJUUhAb1Q %}

All the code is available for free on [GitHub](https://youtu.be/W3bJUUhAb1Q?si=RHFrRhshhXOQn977&t=611) ( You can find the GitHub link within the video description )


## **Designing the Piano in Figma**
The journey begins with the design phase, where I use Figma to create the interface for our digital piano. Figma, known for its adaptability and ease of use, is an excellent tool for such a task. 

### Laying the Foundation

I start by setting up a new design file in Figma, focusing initially on the basic layout. This involves establishing the dimensions of the piano and its positioning on the screen.

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ipwuyeq4lav74gw2qfep.png)](https://youtu.be/W3bJUUhAb1Q?si=F7Ea729IHzPBVVzT&t=115)
### Designing the Piano Keys

A key aspect of the design phase in Figma is setting up and using a grid. The grid serves as a foundational tool to ensure that all elements of the piano, especially the keys, are aligned precisely and proportionately.

I initiate the design process by defining a grid system. This grid helps maintain consistent spacing and alignment across the piano interface. It's particularly important for positioning the piano keys accurately, as their placement needs to mimic the layout of a traditional piano closely.

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gdn442ywuy1vwx8c2tme.png)](https://youtu.be/W3bJUUhAb1Q?si=AWkQS9uUUZPCyGDP&t=127)

There we design the white and the black keys. The black keys are shorter and positioned slightly higher, just like on a real piano. 

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fwfezt2bt59ez4ud29gw.png)](https://youtu.be/W3bJUUhAb1Q?si=cNoJdrON2MK_H2bc&t=178)
After the keys are in place, I add finer details to the design. This includes making the black and the white keys 3D

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/haihm6ot5i5m5nf7f3dz.png)](https://youtu.be/W3bJUUhAb1Q?si=krzgJKTqMhUZtPz-&t=349)
## **Developing the Piano with the use of Semantic HTML**

Transitioning from the design to development, the first step is to set up the basic HTML structure of our digital piano. I begin by creating a foundational HTML document that will house all the components of our piano.

### Creating the container

The buttons are organized within a parent container, maintaining a clean and logical HTML structure that mirrors the layout of a traditional piano.

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k9i7j90y9eaohea13ntb.png)](https://youtu.be/W3bJUUhAb1Q?si=M0uge6gQRc_6Y0O8&t=734)

### Using Buttons for Piano Keys

A crucial aspect of this phase, as detailed in the tutorial, is the use of <button> elements for the piano keys. Instead of using <div> elements, I choose <button> elements for each key because they are more semantically appropriate and accessible.

Buttons are inherently interactive and accessible, making them ideal for our piano keys. They support keyboard focus and click interactions out of the box, which is essential for the functionality of our digital piano.

For each key, I create a <button> element. The white and black keys are differentiated by class names, allowing for specific styling and functionality to be applied later in the SASS and JavaScript phase.

I also ensure that each button is properly labeled with aria-labels, providing screen reader users with the necessary information about the function and note of each key.

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2qhglahavlgzrmu75sro.png)](https://youtu.be/W3bJUUhAb1Q?si=3Q3SK3743o1swJKN&t=870)

To make the piano more user-friendly, especially for beginners or those learning music, I add hints to each key which helps identify which keyboard keys the user can use to play the notes.

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5sl8lx77u4zyt8xbilj2.png)](https://youtu.be/W3bJUUhAb1Q?si=5SIGb5EuqD8SFooW&t=974)

## Styling the Piano Keys with SCSS

Next, I delve into the styling aspect, using SASS or SCSS to be specific - a powerful CSS extension language. You’ll see my approach to organizing SASS files and utilizing its advanced features by using Maps instead of Variables to create a simple design system and our components.

### Utilizing SCSS Maps for Theming

A key feature of my SCSS setup is the use of SCSS maps, particularly the `$theme` and `$piano` maps. These maps are crucial for organizing and managing the various colors, dimensions, and other stylistic properties used in the piano design.

The `$theme` map contains the color scheme and other general design elements that define the overall aesthetic of the piano. This approach allows for easy adjustments and theming, ensuring that changes to the design can be made quickly and consistently.

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b44rwvp86civ8z6vvbo8.png)](https://youtu.be/W3bJUUhAb1Q?si=ZivPZsSmo_89i7qn&t=1219)


The `$piano` map specifically holds the properties related to the piano's design, such as key dimensions, border styles, and positioning. This separation of concerns makes the styling process more manageable, modular and easily updated from one place. 

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xus5iwtcdnc6657dxiu5.png)](https://youtu.be/W3bJUUhAb1Q?si=Bu_v-OIBeCdyY6Qr&t=1577)

Moreover, if you have multiple themes, you can override them.

### How you can create a new theme:
You can create a new dark theme or you can do multiple maps having the same keys but different values.

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tg7dn8ompbz1wdp5t2wi.png)](https://youtu.be/W3bJUUhAb1Q)

### Merge the Themes: Merge the `$theme` and `$dark-theme`
After you do this you can create a new sass map that has the updated values.
![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ocj7u4jvv7edltazxup6.png)

### Reassign `$theme` to `$theme-dark`: This is where you switch the theme.

And then have the new colours applied to the theme and frontend instantly.

![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mvhvbsq90faok581glrw.png)


### Styling the White Keys

The white keys are styled with a focus on simplicity and elegance. Using the properties from the `$piano` map, I define the height, width, and background color for each white key.

Additional styles include border properties and subtle shadow effects to create a sense of depth. These shadows are especially important for achieving the 3D effect that makes the keys feel tactile and interactive.

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/imyhbmami2d92eyz3rng.png)](https://youtu.be/W3bJUUhAb1Q?si=NSAPrN3c8afdpptv&t=2140)
### Styling the Black Keys
The black keys require a different approach. They are smaller and positioned differently. Here, I use the values from the SASS maps to define their unique dimensions and positioning.

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w9ff0unzpxzf9ohdyvw4.png)](https://youtu.be/W3bJUUhAb1Q?si=CWMN8Wp-xlgW1yG8&t=2649)

The color and shadow effects for the black keys are adjusted to make them stand out against the white keys. This involves setting a darker color and tweaking the opacity and spread of the shadows to enhance the 3D appearance.

### 3D interactive Key Styling in a Digital Piano

A standout feature in the digital piano's design is the realistic response of its keys when pressed. This effect is achieved through careful styling in SCSS, particularly in the `.is-pressed` state for both black and white keys.

### Black Keys: A Deeper Perspective

For the black keys, pressing a key triggers a transformation defined by `perspective(1500px) rotateX(-6deg)`. This effect creates a visual depth, making the key appear as if it's being pressed down. The larger perspective value enhances the depth illusion, while the rotateX tilt simulates the downward motion.

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ehdzdu6hm3tzeawnfhu.png)](https://youtu.be/W3bJUUhAb1Q?si=M3c4QIr6VTp9nfkV&t=2704)

### White Keys: A Subtler Motion

The white keys, in contrast, exhibit a more subtle motion with `perspective(330px) rotateX(-2deg)`. This difference reflects the distinct physical characteristics of white piano keys. The transformation is less pronounced yet equally effective in conveying the sense of a key being pressed.

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9srdpbms68zs6bx6dvsu.png)](https://youtu.be/W3bJUUhAb1Q)

Both key types utilize `transition: transform 0.2s` to ensure the animation is fluid and natural. This careful timing makes the interaction feel responsive and intuitive.


## Introducing interactivity with Vanilla JavaScript

As I reach the final part of my tutorial, I delve into how to add interactivity and code functionality using JavaScript. This phase is crucial as it transforms the digital piano from a static design into an interactive musical instrument.

### Setting Up the JavaScript Environment


Initially, I discuss the JavaScript file setup. Given that we're using Webpack, I explain the use of dynamic imports for styles and how Webpack compiles them efficiently.

To maintain a clean codebase, I emphasize the importance of separating concerns. Hence, I create a dedicated JavaScript folder, paralleling the structure we used for styles.

### Creating the Piano Component
The first step in coding the functionality is to create a component named `Piano.js`. This component is structured as a constructor function, allowing for reusability in different parts of the application.

I ensure to export the Piano component using the export operator.

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/enq904qcbnrz311321go.png)](https://youtu.be/W3bJUUhAb1Q?si=Hey-g9LfQEBRcm70&t=2979)

The Piano function returns an object containing both `playNote` and `playNoteByKey` functions. This return statement makes these functions accessible to other parts of the application, adhering to the principles of the Module pattern.

The `Piano.js` file uses a modular pattern, a common and effective approach in JavaScript, to encapsulate functionality. It starts with importing `keyboardMap` from the keybinds module. This map is crucial as it correlates keyboard keys to musical notes, an essential aspect of the piano's interactivity.

### `playNote` Function

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w6zj850s686tbjkyzjbb.png)](https://youtu.be/W3bJUUhAb1Q?si=zcKSOwfp4NieKsLj&t=3049)

The `audio.play()` method is then invoked to play the note. This simple yet effective line of code is the heart of the piano's sound functionality.

A key aspect of this function is the use of the HTML audio element, a powerful web API for manipulating audio files dynamically. This API allows for playing and pausing audio, which is crucial for a web application like a digital piano.

### `index.js` Imports
Inside `index.js` or our entry point we import our Styles and Components.

`import "./styles/main.scss";` 
Imports the main SASS stylesheet, ensuring all styles are applied to the piano interface.

`import { Piano } from "./javascript/Piano";` 
Imports the Piano function, which encapsulates the core functionality for playing notes.

`import { keyboardMap } from "./javascript/keybinds";` 
Imports the mapping of keyboard keys to piano notes, crucial for enabling keyboard interactivity.

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cdyr8nf9nfwyuw2dw4k8.png)](https://youtu.be/W3bJUUhAb1Q?si=Jpp9BbSJNtmJCrmo&t=3409)
### Initializing the Digital Piano

`const DigitalPiano = Piano();` 
Initializes the digital piano by invoking the Piano function. This instance, DigitalPiano, is now equipped with methods to play notes.

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nmto2bwlg6baejr880le.png)](https://youtu.be/W3bJUUhAb1Q?si=F2t431JGUCvmMyL6&t=3424)
### Creating UI Note-Keybind Map

This function creates a mapping between the data attributes of the piano keys (notes) and the HTML elements themselves. This map is used to find the corresponding DOM element efficiently when a note is played.

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9qlwyat3isp5kxvmkkn3.png)](https://youtu.be/W3bJUUhAb1Q?si=mISU9qXStGkK6w-y&t=3591)

### Handling Mouse Events

`handleMouseDown` and `handleMouseUp` are event handlers for mouse down and up events on each key. When a key is pressed (mouse down), it adds the `.is-pressed` class for visual feedback and plays the corresponding note. On mouse up, it removes the is-pressed class.
`handleDocumentMouseUp` removes the `.is-pressed` class from all keys, ensuring that any stuck keys are released if the mouse is released outside a key.

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4p5lrh5h1bqlzl7wswce.png)](https://youtu.be/W3bJUUhAb1Q?si=EENE2HHiooRazaJz&t=3778)
### Handling Keyboard Events

`findNoteAndNodeFromKeyPress` is a utility function to find the note and corresponding DOM node based on a keyboard event.

`handleDocumentKeyDown` and `handleDocumentKeyUp` are event handlers for keyboard events. They use `findNoteAndNodeFromKeyPress` to play the corresponding note and toggle the `.is-pressed` class based on key down and up events.

[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rgsoe9o28i1i62kjlsu2.png)](https://youtu.be/W3bJUUhAb1Q?si=bMLKy7sYvmtgpQif&t=4276)

### Adding Event Listeners

The document-level event listeners for `mouseup`, `keydown`, and `keyup` handle global actions like releasing all keys when the mouse button is released, and playing notes based on keyboard input.
Each piano key node has event listeners for `mousedown` and `mouseup` to handle individual key interactions.


[![Link to YouTube Video](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6erqeh5zxtxi1zgxl907.png)](https://youtu.be/W3bJUUhAb1Q?si=ZJN3XtbwvhfCZ-bo&t=4425)

## Conclusion
And there we have it—the final chord in our digital piano creation symphony. Through this journey, we've navigated the harmonious blend of design and development, starting from the conceptual sketches in Figma to the functional, interactive keys brought to life with JavaScript. 

This project wasn't just about building a musical instrument; it was about harmonizing different technologies to create something beautiful and functional. I hope this experience leaves you with not only a deeper understanding of web development and design but also the inspiration to blend art and technology in your future projects. 

Thank you for joining me on this melodious coding journey. Keep experimenting, keep learning, and let your creativity play the next tune!

If you want to watch the video instead, you can watch it by clicking the YouTube video below:

{% embed https://youtu.be/W3bJUUhAb1Q %}

All the code is available for free on [GitHub](https://youtu.be/W3bJUUhAb1Q?si=RHFrRhshhXOQn977&t=611) ( You can find the GitHub link within the video description )