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:
All the code is available for free on GitHub ( 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.
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.
There we design the white and the black keys. The black keys are shorter and positioned slightly higher, just like on a real piano.
After the keys are in place, I add finer details to the design. This includes making the black and the white keys 3D
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.
Using Buttons for Piano Keys
A crucial aspect of this phase, as detailed in the tutorial, is the use of elements for the piano keys. Instead of using elements, I choose 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 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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
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.
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.
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.
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.
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.
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.
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:
All the code is available for free on GitHub ( You can find the GitHub link within the video description )
Top comments (7)
Thanks, interesting approach 👍 one note: the GitHub link leads to YouTube, or is it only me?
Thanks for your comment @fyodorio, I've updated the link so it now directs to the section detailing how to install and run the repository locally. You can find the link within the video description as the first link and the Figma design files.
Additionally, here's the direct link to the GitHub repository for your convenience.
This is amazing! Thanks for sharing!
Hearing your positive feedback, Arjun, is truly rewarding. Glad you enjoyed it!
thanks for this article!
Thanks for your support Fransceco!!!
you are welcome!