I’m developing a piano keyboard using HTML + CSS.
My code structure is as follows:
:root {
--piano-width: 600px;
--piano-height: 150px;
--piano-keys-gap: 1px;
--piano-black-keys-height-perc: 0.6;
}
.piano-keys {
display: flex;
flex-direction: row;
justify-content: center;
width: var(--piano-width);
height: var(--piano-height);
}
.piano-key {
position: relative;
box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.2);
cursor: pointer;
}
.piano-key.key-white {
background-color: #eeeeee;
flex-basis: 100%;
}
.piano-key.key-black {
background-color: #333;
flex-basis: 90%;
height: calc(var(--piano-height) * var(--piano-black-keys-height-perc));
z-index: 1;
margin-left: -HALF_CURRENT_SIZE;
margin-right: -HALF_CURRENT_SIZE;
}
<div class="piano-container">
<div class="piano-keys">
<div class="piano-key key-white note-selector" data-note="C" selected>C</div>
<div class="piano-key key-black note-selector" data-note="C#" has-acidental>C#</div>
...
<div class="piano-key key-white note-selector" data-note="B">B</div>
</div>
</div>
I want a way to position the black keys over the white keys, considering that:
- The width of the keys is dynamic, they must fill the size of the parent div
- The width of the black keys is a little smaller than the width of the white keys (about 100% flex basis for white, and 90% flex basis for black)
- I want to be able to control the GAP between the keys, in px
I found on a website that by placing a negative horizontal margin of half the width of the key on each side, it overlaps, with the desired effect. But since the width is dynamic, I couldn’t do this.
Is there a way to achieve this effect without using JavaScript?
2
Answers
Just a proposal…
The example below is the full 88 keys with natural, flat, and sharp notes labeled. There are comments for
.black-key
dimensions if you want a more accurate scale and more space between them. In a responsive layout an absolute unit likepx
isn’t very optimal. Positioning of.black-key
was done with negativemargin-left
. The majority of the lengths are inrem
units which are relative to the:root
font-size
which is based onvmax
units which is based on the larger length of the viewport. Basically if the window’s width is bigger than the height, then allrem
s will scale to that and vice versa should the window’s height be greater than it’s width. View in Full page mode and resize the window to review it’s responsiveness. Details are commented in the example.